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

     1  package emitter
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/unicornultrafoundation/go-helios/emitter/ancestor"
     8  	"github.com/unicornultrafoundation/go-helios/native/idx"
     9  	"github.com/unicornultrafoundation/go-helios/native/pos"
    10  	"github.com/unicornultrafoundation/go-u2u/core/types"
    11  
    12  	"github.com/unicornultrafoundation/go-u2u/native"
    13  	"github.com/unicornultrafoundation/go-u2u/utils/adapters/vecmt2dagidx"
    14  	"github.com/unicornultrafoundation/go-u2u/version"
    15  )
    16  
    17  var (
    18  	fcVersion = version.ToU64(1, 1, 3)
    19  )
    20  
    21  // OnNewEpoch should be called after each epoch change, and on startup
    22  func (em *Emitter) OnNewEpoch(newValidators *pos.Validators, newEpoch idx.Epoch) {
    23  	em.maxParents = em.config.MaxParents
    24  	rules := em.world.GetRules()
    25  	if em.maxParents == 0 {
    26  		em.maxParents = rules.Dag.MaxParents
    27  	}
    28  	if em.maxParents > rules.Dag.MaxParents {
    29  		em.maxParents = rules.Dag.MaxParents
    30  	}
    31  	if em.validators != nil && em.isValidator() && !em.validators.Exists(em.config.Validator.ID) && newValidators.Exists(em.config.Validator.ID) {
    32  		em.syncStatus.becameValidator = time.Now()
    33  	}
    34  
    35  	em.validators, em.epoch = newValidators, newEpoch
    36  
    37  	if !em.isValidator() {
    38  		return
    39  	}
    40  	em.prevEmittedAtTime = em.loadPrevEmitTime()
    41  
    42  	em.originatedTxs.Clear()
    43  	em.pendingGas = 0
    44  
    45  	em.offlineValidators = make(map[idx.ValidatorID]bool)
    46  	em.challenges = make(map[idx.ValidatorID]time.Time)
    47  	em.expectedEmitIntervals = make(map[idx.ValidatorID]time.Duration)
    48  	em.stakeRatio = make(map[idx.ValidatorID]uint64)
    49  
    50  	em.recountValidators(newValidators)
    51  
    52  	if em.switchToFCIndexer {
    53  		em.quorumIndexer = nil
    54  		em.fcIndexer = ancestor.NewFCIndexer(newValidators, em.world.DagIndex(), em.config.Validator.ID)
    55  	} else {
    56  		em.quorumIndexer = ancestor.NewQuorumIndexer(newValidators, vecmt2dagidx.Wrap(em.world.DagIndex()),
    57  			func(median, current, update idx.Event, validatorIdx idx.Validator) ancestor.Metric {
    58  				return updMetric(median, current, update, validatorIdx, newValidators)
    59  			})
    60  		em.fcIndexer = nil
    61  	}
    62  	em.quorumIndexer = ancestor.NewQuorumIndexer(newValidators, vecmt2dagidx.Wrap(em.world.DagIndex()),
    63  		func(median, current, update idx.Event, validatorIdx idx.Validator) ancestor.Metric {
    64  			return updMetric(median, current, update, validatorIdx, newValidators)
    65  		})
    66  	em.payloadIndexer = ancestor.NewPayloadIndexer(PayloadIndexerSize)
    67  }
    68  
    69  func (em *Emitter) handleVersionUpdate(e native.EventPayloadI) {
    70  	if e.Seq() <= 1 && len(e.Extra()) > 0 {
    71  		var (
    72  			vMajor int
    73  			vMinor int
    74  			vPatch int
    75  			vMeta  string
    76  		)
    77  		n, err := fmt.Sscanf(string(e.Extra()), "v-%d.%d.%d-%s", &vMajor, &vMinor, &vPatch, &vMeta)
    78  		if n == 4 && err == nil {
    79  			em.validatorVersions[e.Creator()] = version.ToU64(uint16(vMajor), uint16(vMinor), uint16(vPatch))
    80  		}
    81  	}
    82  }
    83  
    84  func (em *Emitter) fcValidators() pos.Weight {
    85  	counter := pos.Weight(0)
    86  	for v, ver := range em.validatorVersions {
    87  		if ver >= fcVersion {
    88  			counter += em.validators.Get(v)
    89  		}
    90  	}
    91  	return counter
    92  }
    93  
    94  // OnEventConnected tracks new events
    95  func (em *Emitter) OnEventConnected(e native.EventPayloadI) {
    96  	em.handleVersionUpdate(e)
    97  	if !em.switchToFCIndexer && em.fcValidators() >= pos.Weight(uint64(em.validators.TotalWeight())*5/6) {
    98  		em.switchToFCIndexer = true
    99  	}
   100  	if !em.isValidator() {
   101  		return
   102  	}
   103  	if em.fcIndexer != nil {
   104  		em.fcIndexer.ProcessEvent(e)
   105  	} else if em.quorumIndexer != nil {
   106  		em.quorumIndexer.ProcessEvent(e, e.Creator() == em.config.Validator.ID)
   107  	}
   108  	em.payloadIndexer.ProcessEvent(e, ancestor.Metric(e.Txs().Len()))
   109  	for _, tx := range e.Txs() {
   110  		addr, _ := types.Sender(em.world.TxSigner, tx)
   111  		em.originatedTxs.Inc(addr)
   112  	}
   113  	em.pendingGas += e.GasPowerUsed()
   114  	if e.Creator() == em.config.Validator.ID && em.syncStatus.prevLocalEmittedID != e.ID() {
   115  		// event was emitted by me on another instance
   116  		em.onNewExternalEvent(e)
   117  	}
   118  	// if there was any challenge, erase it
   119  	delete(em.challenges, e.Creator())
   120  	// mark validator as online
   121  	delete(em.offlineValidators, e.Creator())
   122  }
   123  
   124  func (em *Emitter) OnEventConfirmed(he native.EventI) {
   125  	if !em.isValidator() {
   126  		return
   127  	}
   128  	if em.pendingGas > he.GasPowerUsed() {
   129  		em.pendingGas -= he.GasPowerUsed()
   130  	} else {
   131  		em.pendingGas = 0
   132  	}
   133  	if he.AnyTxs() {
   134  		e := em.world.GetEventPayload(he.ID())
   135  		for _, tx := range e.Txs() {
   136  			addr, _ := types.Sender(em.world.TxSigner, tx)
   137  			em.originatedTxs.Dec(addr)
   138  		}
   139  	}
   140  }