github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/emitter/validators.go (about)

     1  package emitter
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/unicornultrafoundation/go-helios/native/idx"
     7  	"github.com/unicornultrafoundation/go-helios/native/pos"
     8  	"github.com/unicornultrafoundation/go-helios/utils/piecefunc"
     9  )
    10  
    11  const (
    12  	validatorChallenge = 4 * time.Second
    13  	networkStartPeriod = 3 * time.Hour
    14  )
    15  
    16  func (em *Emitter) recountValidators(validators *pos.Validators) {
    17  	// stakers with lower stake should emit less events to reduce network load
    18  	// confirmingEmitInterval = piecefunc(totalStakeBeforeMe / totalStake) * MinEmitInterval
    19  	totalStakeBefore := pos.Weight(0)
    20  	for i, stake := range validators.SortedWeights() {
    21  		vid := validators.GetID(idx.Validator(i))
    22  		// pos.Weight is uint32, so cast to uint64 to avoid an overflow
    23  		stakeRatio := uint64(totalStakeBefore) * uint64(piecefunc.DecimalUnit) / uint64(validators.TotalWeight())
    24  		if !em.offlineValidators[vid] {
    25  			totalStakeBefore += stake
    26  		}
    27  		confirmingEmitIntervalRatio := confirmingEmitIntervalF(stakeRatio)
    28  		em.stakeRatio[vid] = stakeRatio
    29  		em.expectedEmitIntervals[vid] = time.Duration(piecefunc.Mul(uint64(em.config.EmitIntervals.Confirming), confirmingEmitIntervalRatio))
    30  	}
    31  	em.intervals.Confirming = em.expectedEmitIntervals[em.config.Validator.ID]
    32  	em.intervals.Max = em.config.EmitIntervals.Max
    33  	// if network just has started, then relax the doublesign protection
    34  	if time.Since(em.world.GetGenesisTime().Time()) < networkStartPeriod {
    35  		em.intervals.Max /= 6
    36  		em.intervals.DoublesignProtection /= 6
    37  	}
    38  }
    39  
    40  func (em *Emitter) recheckChallenges() {
    41  	if time.Since(em.prevRecheckedChallenges) < validatorChallenge/10 {
    42  		return
    43  	}
    44  	em.world.Lock()
    45  	defer em.world.Unlock()
    46  	now := time.Now()
    47  	if !em.idle() {
    48  		// give challenges to all the non-spare validators if network isn't idle
    49  		for _, vid := range em.validators.IDs() {
    50  			if em.offlineValidators[vid] {
    51  				continue
    52  			}
    53  			if _, ok := em.challenges[vid]; !ok {
    54  				em.challenges[vid] = now.Add(validatorChallenge + em.expectedEmitIntervals[vid]*4)
    55  			}
    56  		}
    57  	} else {
    58  		// erase all the challenges if network is idle
    59  		em.challenges = make(map[idx.ValidatorID]time.Time)
    60  	}
    61  	// check challenges
    62  	recount := false
    63  	for vid, challengeDeadline := range em.challenges {
    64  		if now.After(challengeDeadline) {
    65  			em.offlineValidators[vid] = true
    66  			recount = true
    67  		}
    68  	}
    69  	if recount {
    70  		em.recountValidators(em.validators)
    71  	}
    72  	em.prevRecheckedChallenges = now
    73  }