github.com/turingchain2020/turingchain@v1.1.21/system/mempool/cache.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found In the LICENSE file. 4 5 package mempool 6 7 import ( 8 "github.com/turingchain2020/turingchain/types" 9 ) 10 11 //QueueCache 排队交易处理 12 type QueueCache interface { 13 Exist(hash string) bool 14 GetItem(hash string) (*Item, error) 15 Push(tx *Item) error 16 Remove(hash string) error 17 Size() int 18 Walk(count int, cb func(tx *Item) bool) 19 GetProperFee() int64 20 GetCacheBytes() int64 21 } 22 23 // Item 为Mempool中包装交易的数据结构 24 type Item struct { 25 Value *types.Transaction 26 Priority int64 27 EnterTime int64 28 } 29 30 //TxCache 管理交易cache 包括账户索引,最后的交易,排队策略缓存 31 type txCache struct { 32 *AccountTxIndex 33 *LastTxCache 34 qcache QueueCache 35 totalFee int64 36 *SHashTxCache 37 } 38 39 //NewTxCache init accountIndex and last cache 40 func newCache(maxTxPerAccount int64, sizeLast int64, poolCacheSize int64) *txCache { 41 return &txCache{ 42 AccountTxIndex: NewAccountTxIndex(int(maxTxPerAccount)), 43 LastTxCache: NewLastTxCache(int(sizeLast)), 44 SHashTxCache: NewSHashTxCache(int(poolCacheSize)), 45 } 46 } 47 48 //SetQueueCache set queue cache , 这个接口可以扩展 49 func (cache *txCache) SetQueueCache(qcache QueueCache) { 50 cache.qcache = qcache 51 } 52 53 //Remove 移除txCache中给定tx 54 func (cache *txCache) Remove(hash string) { 55 item, err := cache.qcache.GetItem(hash) 56 if err != nil { 57 return 58 } 59 tx := item.Value 60 err = cache.qcache.Remove(hash) 61 if err != nil { 62 mlog.Error("Remove", "cache Remove err", err) 63 } 64 cache.AccountTxIndex.Remove(tx) 65 cache.LastTxCache.Remove(tx) 66 cache.totalFee -= tx.Fee 67 cache.SHashTxCache.Remove(tx) 68 } 69 70 //Exist 是否存在 71 func (cache *txCache) Exist(hash string) bool { 72 if cache.qcache == nil { 73 return false 74 } 75 return cache.qcache.Exist(hash) 76 } 77 78 //Size cache tx num 79 func (cache *txCache) Size() int { 80 if cache.qcache == nil { 81 return 0 82 } 83 return cache.qcache.Size() 84 } 85 86 //TotalFee 手续费总和 87 func (cache *txCache) TotalFee() int64 { 88 return cache.totalFee 89 } 90 91 //Walk iter all txs 92 func (cache *txCache) Walk(count int, cb func(tx *Item) bool) { 93 if cache.qcache == nil { 94 return 95 } 96 cache.qcache.Walk(count, cb) 97 } 98 99 //RemoveTxs 删除一组交易 100 func (cache *txCache) RemoveTxs(txs []string) { 101 for _, t := range txs { 102 cache.Remove(t) 103 } 104 } 105 106 //Push 存入交易到cache 中 107 func (cache *txCache) Push(tx *types.Transaction) error { 108 if !cache.AccountTxIndex.CanPush(tx) { 109 return types.ErrManyTx 110 } 111 item := &Item{Value: tx, Priority: tx.Fee, EnterTime: types.Now().Unix()} 112 err := cache.qcache.Push(item) 113 if err != nil { 114 return err 115 } 116 err = cache.AccountTxIndex.Push(tx) 117 if err != nil { 118 return err 119 } 120 cache.LastTxCache.Push(tx) 121 cache.totalFee += tx.Fee 122 cache.SHashTxCache.Push(tx) 123 return nil 124 } 125 126 func (cache *txCache) removeExpiredTx(cfg *types.TuringchainConfig, height, blocktime int64) { 127 var txs []string 128 cache.qcache.Walk(0, func(tx *Item) bool { 129 if isExpired(cfg, tx, height, blocktime) { 130 txs = append(txs, string(tx.Value.Hash())) 131 } 132 return true 133 }) 134 if len(txs) > 0 { 135 mlog.Info("removeExpiredTx", "height", height, "totalTxs", cache.Size(), "expiredTxs", len(txs)) 136 cache.RemoveTxs(txs) 137 } 138 } 139 140 //判断交易是否过期 141 func isExpired(cfg *types.TuringchainConfig, item *Item, height, blockTime int64) bool { 142 if types.Now().Unix()-item.EnterTime >= mempoolExpiredInterval { 143 return true 144 } 145 if item.Value.IsExpire(cfg, height, blockTime) { 146 return true 147 } 148 return false 149 } 150 151 //getTxByHash 通过交易hash获取tx交易信息 152 func (cache *txCache) getTxByHash(hash string) *types.Transaction { 153 item, err := cache.qcache.GetItem(hash) 154 if err != nil { 155 return nil 156 } 157 return item.Value 158 }