github.com/annchain/OG@v0.0.9/og/txmaker/fifo_tip_generator.go (about) 1 package txmaker 2 3 import ( 4 "github.com/annchain/OG/common" 5 "github.com/annchain/OG/og/types" 6 7 "github.com/sirupsen/logrus" 8 "math/rand" 9 "sync" 10 ) 11 12 // FIFOTipGenerator wraps txpool random picker so that 13 // when tps is low, the graph will not be like a chain. 14 type FIFOTipGenerator struct { 15 maxCacheSize int 16 upstream TipGenerator 17 fifoRing []types.Txi 18 fifoRingPos int 19 fifoRingFull bool 20 mu sync.RWMutex 21 } 22 23 func NewFIFOTIpGenerator(upstream TipGenerator, maxCacheSize int) *FIFOTipGenerator { 24 return &FIFOTipGenerator{ 25 upstream: upstream, 26 maxCacheSize: maxCacheSize, 27 fifoRing: make([]types.Txi, maxCacheSize), 28 } 29 } 30 31 func (f *FIFOTipGenerator) validation() { 32 var k int 33 for i := 0; i < f.maxCacheSize; i++ { 34 if f.fifoRing[i] == nil { 35 if f.fifoRingPos > i { 36 f.fifoRingPos = i 37 } 38 break 39 } 40 //if the tx is became fatal tx ,remove it from tips 41 if !f.fifoRing[i].Valid() { 42 logrus.WithField("tx ", f.fifoRing[i]).Debug("found invalid tx") 43 if !f.fifoRingFull { 44 if f.fifoRingPos > 0 { 45 if f.fifoRingPos-1 == i { 46 f.fifoRing[i] = nil 47 } else if f.fifoRingPos-1 > i { 48 f.fifoRing[i] = f.fifoRing[f.fifoRingPos-1] 49 } else { 50 f.fifoRing[i] = nil 51 break 52 } 53 f.fifoRingPos-- 54 } 55 } else { 56 f.fifoRing[i] = f.fifoRing[f.maxCacheSize-k-1] 57 f.fifoRing[f.maxCacheSize-k-1] = nil 58 i-- 59 k++ 60 f.fifoRingFull = false 61 } 62 } 63 } 64 } 65 66 func (f *FIFOTipGenerator) GetByNonce(addr common.Address, nonce uint64) types.Txi { 67 return f.upstream.GetByNonce(addr, nonce) 68 } 69 70 func (f *FIFOTipGenerator) IsBadSeq(seq *types.Sequencer) error { 71 return f.upstream.IsBadSeq(seq) 72 } 73 74 func (f *FIFOTipGenerator) GetRandomTips(n int) (v []types.Txi) { 75 f.mu.Lock() 76 defer f.mu.Unlock() 77 upstreamTips := f.upstream.GetRandomTips(n) 78 //checkValidation 79 f.validation() 80 // update fifoRing 81 for _, upstreamTip := range upstreamTips { 82 duplicated := false 83 for i := 0; i < f.maxCacheSize; i++ { 84 if f.fifoRing[i] != nil && f.fifoRing[i].GetHash() == upstreamTip.GetHash() { 85 // duplicate, ignore directly 86 duplicated = true 87 break 88 } 89 } 90 if !duplicated { 91 // advance ring and put it in the fifo ring 92 f.fifoRing[f.fifoRingPos] = upstreamTip 93 f.fifoRingPos++ 94 // round 95 if f.fifoRingPos == f.maxCacheSize { 96 f.fifoRingPos = 0 97 f.fifoRingFull = true 98 } 99 } 100 } 101 // randomly pick n from fifo cache 102 randIndices := make(map[int]bool) 103 ringSize := f.fifoRingPos 104 if f.fifoRingFull { 105 ringSize = f.maxCacheSize 106 } 107 pickSize := n 108 if !f.fifoRingFull && f.fifoRingPos < n { 109 pickSize = f.fifoRingPos 110 } 111 112 for len(randIndices) != pickSize { 113 randIndices[rand.Intn(ringSize)] = true 114 } 115 116 // dump those txs 117 for k := range randIndices { 118 v = append(v, f.fifoRing[k]) 119 } 120 return 121 122 }