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 }