github.com/okex/exchain@v1.8.0/libs/tendermint/mempool/gasqueue.go (about) 1 package mempool 2 3 import ( 4 "crypto/sha256" 5 "fmt" 6 "sort" 7 "sync" 8 9 "github.com/okex/exchain/libs/tendermint/libs/clist" 10 ) 11 12 type GasTxQueue struct { 13 txPriceBump int64 14 sortedTxs *clist.CList 15 sortedTxsMap sync.Map 16 bcTxs *clist.CList 17 bcTxsMap sync.Map 18 19 *AddressRecord 20 } 21 22 func NewGasTxQueue(txPriceBump int64) *GasTxQueue { 23 q := &GasTxQueue{ 24 txPriceBump: txPriceBump, 25 sortedTxs: clist.New(), 26 bcTxs: clist.New(), 27 } 28 q.AddressRecord = newAddressRecord(q) 29 return q 30 } 31 32 func (q *GasTxQueue) Len() int { 33 return q.sortedTxs.Len() 34 } 35 36 func (q *GasTxQueue) Insert(memTx *mempoolTx) error { 37 /* 38 1. insert tx list 39 2. insert address record 40 3. insert tx map 41 */ 42 ele := q.AddressRecord.checkRepeatedAndAddItem(memTx, q.txPriceBump, q.sortedTxs.InsertElement) 43 if ele == nil { 44 return fmt.Errorf("failed to replace tx for acccount %s with nonce %d, "+ 45 "the provided gas price %d is not bigger enough", memTx.from, memTx.realTx.GetNonce(), memTx.realTx.GetGasPrice()) 46 } 47 txHash := txOrTxHashToKey(memTx.tx, memTx.realTx.TxHash(), memTx.height) 48 49 q.sortedTxsMap.Store(txHash, ele) 50 51 ele2 := q.bcTxs.PushBack(memTx) 52 ele2.Address = memTx.from 53 q.bcTxsMap.Store(txHash, ele2) 54 return nil 55 } 56 57 func (q *GasTxQueue) Remove(element *clist.CElement) { 58 q.removeElement(element) 59 q.AddressRecord.DeleteItem(element) 60 } 61 62 func (q *GasTxQueue) RemoveByKey(key [32]byte) (ele *clist.CElement) { 63 ele = q.removeElementByKey(key) 64 if ele != nil { 65 q.AddressRecord.DeleteItem(ele) 66 } 67 return 68 } 69 70 func (q *GasTxQueue) Front() *clist.CElement { 71 return q.sortedTxs.Front() 72 } 73 74 func (q *GasTxQueue) Back() *clist.CElement { 75 return q.sortedTxs.Back() 76 } 77 78 func (q *GasTxQueue) BroadcastFront() *clist.CElement { 79 return q.bcTxs.Front() 80 } 81 82 func (q *GasTxQueue) BroadcastLen() int { 83 return q.bcTxs.Len() 84 } 85 86 func (q *GasTxQueue) TxsWaitChan() <-chan struct{} { 87 return q.sortedTxs.WaitChan() 88 } 89 90 func (q *GasTxQueue) Load(hash [sha256.Size]byte) (*clist.CElement, bool) { 91 v, ok := q.sortedTxsMap.Load(hash) 92 if !ok { 93 return nil, false 94 } 95 return v.(*clist.CElement), true 96 } 97 98 func (q *GasTxQueue) CleanItems(address string, nonce uint64) { 99 q.AddressRecord.CleanItems(address, nonce, q.removeElement) 100 } 101 102 func (q *GasTxQueue) reorganizeElements(items []*clist.CElement) { 103 if len(items) == 0 { 104 return 105 } 106 // When inserting, strictly order by nonce, otherwise tx will not appear according to nonce, 107 // resulting in execution failure 108 sort.Slice(items, func(i, j int) bool { return items[i].Nonce < items[j].Nonce }) 109 110 for _, item := range items[1:] { 111 q.sortedTxs.DetachElement(item) 112 item.NewDetachPrev() 113 item.NewDetachNext() 114 } 115 116 for _, item := range items { 117 q.sortedTxs.InsertElement(item) 118 } 119 } 120 121 func (q *GasTxQueue) removeElement(element *clist.CElement) { 122 q.sortedTxs.Remove(element) 123 element.DetachPrev() 124 125 tx := element.Value.(*mempoolTx).tx 126 txHash := txKey(tx) 127 q.sortedTxsMap.Delete(txHash) 128 129 if v, ok := q.bcTxsMap.LoadAndDelete(txHash); ok { 130 ele := v.(*clist.CElement) 131 q.bcTxs.Remove(ele) 132 ele.DetachPrev() 133 } 134 } 135 136 func (q *GasTxQueue) removeElementByKey(key [32]byte) (ret *clist.CElement) { 137 if v, ok := q.sortedTxsMap.LoadAndDelete(key); ok { 138 ret = v.(*clist.CElement) 139 q.sortedTxs.Remove(ret) 140 ret.DetachPrev() 141 142 if v, ok := q.bcTxsMap.LoadAndDelete(key); ok { 143 ele := v.(*clist.CElement) 144 q.bcTxs.Remove(ele) 145 ele.DetachPrev() 146 } 147 } 148 149 return 150 }