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  }