github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/txpool/legacypool/list.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package legacypool
    18  
    19  import (
    20  	"container/heap"
    21  	"math"
    22  	"math/big"
    23  	"slices"
    24  	"sort"
    25  	"sync"
    26  	"sync/atomic"
    27  	"time"
    28  
    29  	"github.com/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/holiman/uint256"
    32  )
    33  
    34  // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
    35  // retrieving sorted transactions from the possibly gapped future queue.
    36  type nonceHeap []uint64
    37  
    38  func (h nonceHeap) Len() int           { return len(h) }
    39  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
    40  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    41  
    42  func (h *nonceHeap) Push(x interface{}) {
    43  	*h = append(*h, x.(uint64))
    44  }
    45  
    46  func (h *nonceHeap) Pop() interface{} {
    47  	old := *h
    48  	n := len(old)
    49  	x := old[n-1]
    50  	old[n-1] = 0
    51  	*h = old[0 : n-1]
    52  	return x
    53  }
    54  
    55  // sortedMap is a nonce->transaction hash map with a heap based index to allow
    56  // iterating over the contents in a nonce-incrementing way.
    57  type sortedMap struct {
    58  	items   map[uint64]*types.Transaction // Hash map storing the transaction data
    59  	index   *nonceHeap                    // Heap of nonces of all the stored transactions (non-strict mode)
    60  	cache   types.Transactions            // Cache of the transactions already sorted
    61  	cacheMu sync.Mutex                    // Mutex covering the cache
    62  }
    63  
    64  // newSortedMap creates a new nonce-sorted transaction map.
    65  func newSortedMap() *sortedMap {
    66  	return &sortedMap{
    67  		items: make(map[uint64]*types.Transaction),
    68  		index: new(nonceHeap),
    69  	}
    70  }
    71  
    72  // Get retrieves the current transactions associated with the given nonce.
    73  func (m *sortedMap) Get(nonce uint64) *types.Transaction {
    74  	return m.items[nonce]
    75  }
    76  
    77  // Put inserts a new transaction into the map, also updating the map's nonce
    78  // index. If a transaction already exists with the same nonce, it's overwritten.
    79  func (m *sortedMap) Put(tx *types.Transaction) {
    80  	nonce := tx.Nonce()
    81  	if m.items[nonce] == nil {
    82  		heap.Push(m.index, nonce)
    83  	}
    84  	m.cacheMu.Lock()
    85  	m.items[nonce], m.cache = tx, nil
    86  	m.cacheMu.Unlock()
    87  }
    88  
    89  // Forward removes all transactions from the map with a nonce lower than the
    90  // provided threshold. Every removed transaction is returned for any post-removal
    91  // maintenance.
    92  func (m *sortedMap) Forward(threshold uint64) types.Transactions {
    93  	var removed types.Transactions
    94  
    95  	// Pop off heap items until the threshold is reached
    96  	for m.index.Len() > 0 && (*m.index)[0] < threshold {
    97  		nonce := heap.Pop(m.index).(uint64)
    98  		removed = append(removed, m.items[nonce])
    99  		delete(m.items, nonce)
   100  	}
   101  	// If we had a cached order, shift the front
   102  	m.cacheMu.Lock()
   103  	if m.cache != nil {
   104  		m.cache = m.cache[len(removed):]
   105  	}
   106  	m.cacheMu.Unlock()
   107  	return removed
   108  }
   109  
   110  // Filter iterates over the list of transactions and removes all of them for which
   111  // the specified function evaluates to true.
   112  // Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
   113  // If you want to do several consecutive filterings, it's therefore better to first
   114  // do a .filter(func1) followed by .Filter(func2) or reheap()
   115  func (m *sortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
   116  	removed := m.filter(filter)
   117  	// If transactions were removed, the heap and cache are ruined
   118  	if len(removed) > 0 {
   119  		m.reheap()
   120  	}
   121  	return removed
   122  }
   123  
   124  func (m *sortedMap) reheap() {
   125  	*m.index = make([]uint64, 0, len(m.items))
   126  	for nonce := range m.items {
   127  		*m.index = append(*m.index, nonce)
   128  	}
   129  	heap.Init(m.index)
   130  	m.cacheMu.Lock()
   131  	m.cache = nil
   132  	m.cacheMu.Unlock()
   133  }
   134  
   135  // filter is identical to Filter, but **does not** regenerate the heap. This method
   136  // should only be used if followed immediately by a call to Filter or reheap()
   137  func (m *sortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
   138  	var removed types.Transactions
   139  
   140  	// Collect all the transactions to filter out
   141  	for nonce, tx := range m.items {
   142  		if filter(tx) {
   143  			removed = append(removed, tx)
   144  			delete(m.items, nonce)
   145  		}
   146  	}
   147  	if len(removed) > 0 {
   148  		m.cacheMu.Lock()
   149  		m.cache = nil
   150  		m.cacheMu.Unlock()
   151  	}
   152  	return removed
   153  }
   154  
   155  // Cap places a hard limit on the number of items, returning all transactions
   156  // exceeding that limit.
   157  func (m *sortedMap) Cap(threshold int) types.Transactions {
   158  	// Short circuit if the number of items is under the limit
   159  	if len(m.items) <= threshold {
   160  		return nil
   161  	}
   162  	// Otherwise gather and drop the highest nonce'd transactions
   163  	var drops types.Transactions
   164  	slices.Sort(*m.index)
   165  	for size := len(m.items); size > threshold; size-- {
   166  		drops = append(drops, m.items[(*m.index)[size-1]])
   167  		delete(m.items, (*m.index)[size-1])
   168  	}
   169  	*m.index = (*m.index)[:threshold]
   170  	// The sorted m.index slice is still a valid heap, so there is no need to
   171  	// reheap after deleting tail items.
   172  
   173  	// If we had a cache, shift the back
   174  	m.cacheMu.Lock()
   175  	if m.cache != nil {
   176  		m.cache = m.cache[:len(m.cache)-len(drops)]
   177  	}
   178  	m.cacheMu.Unlock()
   179  	return drops
   180  }
   181  
   182  // Remove deletes a transaction from the maintained map, returning whether the
   183  // transaction was found.
   184  func (m *sortedMap) Remove(nonce uint64) bool {
   185  	// Short circuit if no transaction is present
   186  	_, ok := m.items[nonce]
   187  	if !ok {
   188  		return false
   189  	}
   190  	// Otherwise delete the transaction and fix the heap index
   191  	for i := 0; i < m.index.Len(); i++ {
   192  		if (*m.index)[i] == nonce {
   193  			heap.Remove(m.index, i)
   194  			break
   195  		}
   196  	}
   197  	delete(m.items, nonce)
   198  	m.cacheMu.Lock()
   199  	m.cache = nil
   200  	m.cacheMu.Unlock()
   201  
   202  	return true
   203  }
   204  
   205  // Ready retrieves a sequentially increasing list of transactions starting at the
   206  // provided nonce that is ready for processing. The returned transactions will be
   207  // removed from the list.
   208  //
   209  // Note, all transactions with nonces lower than start will also be returned to
   210  // prevent getting into an invalid state. This is not something that should ever
   211  // happen but better to be self correcting than failing!
   212  func (m *sortedMap) Ready(start uint64) types.Transactions {
   213  	// Short circuit if no transactions are available
   214  	if m.index.Len() == 0 || (*m.index)[0] > start {
   215  		return nil
   216  	}
   217  	// Otherwise start accumulating incremental transactions
   218  	var ready types.Transactions
   219  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   220  		ready = append(ready, m.items[next])
   221  		delete(m.items, next)
   222  		heap.Pop(m.index)
   223  	}
   224  	m.cacheMu.Lock()
   225  	m.cache = nil
   226  	m.cacheMu.Unlock()
   227  
   228  	return ready
   229  }
   230  
   231  // Len returns the length of the transaction map.
   232  func (m *sortedMap) Len() int {
   233  	return len(m.items)
   234  }
   235  
   236  func (m *sortedMap) flatten() types.Transactions {
   237  	m.cacheMu.Lock()
   238  	defer m.cacheMu.Unlock()
   239  	// If the sorting was not cached yet, create and cache it
   240  	if m.cache == nil {
   241  		m.cache = make(types.Transactions, 0, len(m.items))
   242  		for _, tx := range m.items {
   243  			m.cache = append(m.cache, tx)
   244  		}
   245  		sort.Sort(types.TxByNonce(m.cache))
   246  	}
   247  	return m.cache
   248  }
   249  
   250  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   251  // sorted internal representation. The result of the sorting is cached in case
   252  // it's requested again before any modifications are made to the contents.
   253  func (m *sortedMap) Flatten() types.Transactions {
   254  	cache := m.flatten()
   255  	// Copy the cache to prevent accidental modification
   256  	txs := make(types.Transactions, len(cache))
   257  	copy(txs, cache)
   258  	return txs
   259  }
   260  
   261  // LastElement returns the last element of a flattened list, thus, the
   262  // transaction with the highest nonce
   263  func (m *sortedMap) LastElement() *types.Transaction {
   264  	cache := m.flatten()
   265  	return cache[len(cache)-1]
   266  }
   267  
   268  // list is a "list" of transactions belonging to an account, sorted by account
   269  // nonce. The same type can be used both for storing contiguous transactions for
   270  // the executable/pending queue; and for storing gapped transactions for the non-
   271  // executable/future queue, with minor behavioral changes.
   272  type list struct {
   273  	strict bool       // Whether nonces are strictly continuous or not
   274  	txs    *sortedMap // Heap indexed sorted hash map of the transactions
   275  
   276  	costcap   *uint256.Int // Price of the highest costing transaction (reset only if exceeds balance)
   277  	gascap    uint64       // Gas limit of the highest spending transaction (reset only if exceeds block limit)
   278  	totalcost *uint256.Int // Total cost of all transactions in the list
   279  }
   280  
   281  // newList creates a new transaction list for maintaining nonce-indexable fast,
   282  // gapped, sortable transaction lists.
   283  func newList(strict bool) *list {
   284  	return &list{
   285  		strict:    strict,
   286  		txs:       newSortedMap(),
   287  		costcap:   new(uint256.Int),
   288  		totalcost: new(uint256.Int),
   289  	}
   290  }
   291  
   292  // Contains returns whether the  list contains a transaction
   293  // with the provided nonce.
   294  func (l *list) Contains(nonce uint64) bool {
   295  	return l.txs.Get(nonce) != nil
   296  }
   297  
   298  // Add tries to insert a new transaction into the list, returning whether the
   299  // transaction was accepted, and if yes, any previous transaction it replaced.
   300  //
   301  // If the new transaction is accepted into the list, the lists' cost and gas
   302  // thresholds are also potentially updated.
   303  func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
   304  	// If there's an older better transaction, abort
   305  	old := l.txs.Get(tx.Nonce())
   306  	if old != nil {
   307  		if old.GasFeeCapCmp(tx) >= 0 || old.GasTipCapCmp(tx) >= 0 {
   308  			return false, nil
   309  		}
   310  		// thresholdFeeCap = oldFC  * (100 + priceBump) / 100
   311  		a := big.NewInt(100 + int64(priceBump))
   312  		aFeeCap := new(big.Int).Mul(a, old.GasFeeCap())
   313  		aTip := a.Mul(a, old.GasTipCap())
   314  
   315  		// thresholdTip    = oldTip * (100 + priceBump) / 100
   316  		b := big.NewInt(100)
   317  		thresholdFeeCap := aFeeCap.Div(aFeeCap, b)
   318  		thresholdTip := aTip.Div(aTip, b)
   319  
   320  		// We have to ensure that both the new fee cap and tip are higher than the
   321  		// old ones as well as checking the percentage threshold to ensure that
   322  		// this is accurate for low (Wei-level) gas price replacements.
   323  		if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 {
   324  			return false, nil
   325  		}
   326  		// Old is being replaced, subtract old cost
   327  		l.subTotalCost([]*types.Transaction{old})
   328  	}
   329  	// Add new tx cost to totalcost
   330  	cost, overflow := uint256.FromBig(tx.Cost())
   331  	if overflow {
   332  		return false, nil
   333  	}
   334  	l.totalcost.Add(l.totalcost, cost)
   335  
   336  	// Otherwise overwrite the old transaction with the current one
   337  	l.txs.Put(tx)
   338  	if l.costcap.Cmp(cost) < 0 {
   339  		l.costcap = cost
   340  	}
   341  	if gas := tx.Gas(); l.gascap < gas {
   342  		l.gascap = gas
   343  	}
   344  	return true, old
   345  }
   346  
   347  // Forward removes all transactions from the list with a nonce lower than the
   348  // provided threshold. Every removed transaction is returned for any post-removal
   349  // maintenance.
   350  func (l *list) Forward(threshold uint64) types.Transactions {
   351  	txs := l.txs.Forward(threshold)
   352  	l.subTotalCost(txs)
   353  	return txs
   354  }
   355  
   356  // Filter removes all transactions from the list with a cost or gas limit higher
   357  // than the provided thresholds. Every removed transaction is returned for any
   358  // post-removal maintenance. Strict-mode invalidated transactions are also
   359  // returned.
   360  //
   361  // This method uses the cached costcap and gascap to quickly decide if there's even
   362  // a point in calculating all the costs or if the balance covers all. If the threshold
   363  // is lower than the costgas cap, the caps will be reset to a new high after removing
   364  // the newly invalidated transactions.
   365  func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
   366  	// If all transactions are below the threshold, short circuit
   367  	if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
   368  		return nil, nil
   369  	}
   370  	l.costcap = new(uint256.Int).Set(costLimit) // Lower the caps to the thresholds
   371  	l.gascap = gasLimit
   372  
   373  	// Filter out all the transactions above the account's funds
   374  	removed := l.txs.Filter(func(tx *types.Transaction) bool {
   375  		return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit.ToBig()) > 0
   376  	})
   377  
   378  	if len(removed) == 0 {
   379  		return nil, nil
   380  	}
   381  	var invalids types.Transactions
   382  	// If the list was strict, filter anything above the lowest nonce
   383  	if l.strict {
   384  		lowest := uint64(math.MaxUint64)
   385  		for _, tx := range removed {
   386  			if nonce := tx.Nonce(); lowest > nonce {
   387  				lowest = nonce
   388  			}
   389  		}
   390  		invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
   391  	}
   392  	// Reset total cost
   393  	l.subTotalCost(removed)
   394  	l.subTotalCost(invalids)
   395  	l.txs.reheap()
   396  	return removed, invalids
   397  }
   398  
   399  // Cap places a hard limit on the number of items, returning all transactions
   400  // exceeding that limit.
   401  func (l *list) Cap(threshold int) types.Transactions {
   402  	txs := l.txs.Cap(threshold)
   403  	l.subTotalCost(txs)
   404  	return txs
   405  }
   406  
   407  // Remove deletes a transaction from the maintained list, returning whether the
   408  // transaction was found, and also returning any transaction invalidated due to
   409  // the deletion (strict mode only).
   410  func (l *list) Remove(tx *types.Transaction) (bool, types.Transactions) {
   411  	// Remove the transaction from the set
   412  	nonce := tx.Nonce()
   413  	if removed := l.txs.Remove(nonce); !removed {
   414  		return false, nil
   415  	}
   416  	l.subTotalCost([]*types.Transaction{tx})
   417  	// In strict mode, filter out non-executable transactions
   418  	if l.strict {
   419  		txs := l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce })
   420  		l.subTotalCost(txs)
   421  		return true, txs
   422  	}
   423  	return true, nil
   424  }
   425  
   426  // Ready retrieves a sequentially increasing list of transactions starting at the
   427  // provided nonce that is ready for processing. The returned transactions will be
   428  // removed from the list.
   429  //
   430  // Note, all transactions with nonces lower than start will also be returned to
   431  // prevent getting into an invalid state. This is not something that should ever
   432  // happen but better to be self correcting than failing!
   433  func (l *list) Ready(start uint64) types.Transactions {
   434  	txs := l.txs.Ready(start)
   435  	l.subTotalCost(txs)
   436  	return txs
   437  }
   438  
   439  // Len returns the length of the transaction list.
   440  func (l *list) Len() int {
   441  	return l.txs.Len()
   442  }
   443  
   444  // Empty returns whether the list of transactions is empty or not.
   445  func (l *list) Empty() bool {
   446  	return l.Len() == 0
   447  }
   448  
   449  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   450  // sorted internal representation. The result of the sorting is cached in case
   451  // it's requested again before any modifications are made to the contents.
   452  func (l *list) Flatten() types.Transactions {
   453  	return l.txs.Flatten()
   454  }
   455  
   456  // LastElement returns the last element of a flattened list, thus, the
   457  // transaction with the highest nonce
   458  func (l *list) LastElement() *types.Transaction {
   459  	return l.txs.LastElement()
   460  }
   461  
   462  // subTotalCost subtracts the cost of the given transactions from the
   463  // total cost of all transactions.
   464  func (l *list) subTotalCost(txs []*types.Transaction) {
   465  	for _, tx := range txs {
   466  		_, underflow := l.totalcost.SubOverflow(l.totalcost, uint256.MustFromBig(tx.Cost()))
   467  		if underflow {
   468  			panic("totalcost underflow")
   469  		}
   470  	}
   471  }
   472  
   473  // priceHeap is a heap.Interface implementation over transactions for retrieving
   474  // price-sorted transactions to discard when the pool fills up. If baseFee is set
   475  // then the heap is sorted based on the effective tip based on the given base fee.
   476  // If baseFee is nil then the sorting is based on gasFeeCap.
   477  type priceHeap struct {
   478  	baseFee *big.Int // heap should always be re-sorted after baseFee is changed
   479  	list    []*types.Transaction
   480  }
   481  
   482  func (h *priceHeap) Len() int      { return len(h.list) }
   483  func (h *priceHeap) Swap(i, j int) { h.list[i], h.list[j] = h.list[j], h.list[i] }
   484  
   485  func (h *priceHeap) Less(i, j int) bool {
   486  	switch h.cmp(h.list[i], h.list[j]) {
   487  	case -1:
   488  		return true
   489  	case 1:
   490  		return false
   491  	default:
   492  		return h.list[i].Nonce() > h.list[j].Nonce()
   493  	}
   494  }
   495  
   496  func (h *priceHeap) cmp(a, b *types.Transaction) int {
   497  	if h.baseFee != nil {
   498  		// Compare effective tips if baseFee is specified
   499  		if c := a.EffectiveGasTipCmp(b, h.baseFee); c != 0 {
   500  			return c
   501  		}
   502  	}
   503  	// Compare fee caps if baseFee is not specified or effective tips are equal
   504  	if c := a.GasFeeCapCmp(b); c != 0 {
   505  		return c
   506  	}
   507  	// Compare tips if effective tips and fee caps are equal
   508  	return a.GasTipCapCmp(b)
   509  }
   510  
   511  func (h *priceHeap) Push(x interface{}) {
   512  	tx := x.(*types.Transaction)
   513  	h.list = append(h.list, tx)
   514  }
   515  
   516  func (h *priceHeap) Pop() interface{} {
   517  	old := h.list
   518  	n := len(old)
   519  	x := old[n-1]
   520  	old[n-1] = nil
   521  	h.list = old[0 : n-1]
   522  	return x
   523  }
   524  
   525  // pricedList is a price-sorted heap to allow operating on transactions pool
   526  // contents in a price-incrementing way. It's built upon the all transactions
   527  // in txpool but only interested in the remote part. It means only remote transactions
   528  // will be considered for tracking, sorting, eviction, etc.
   529  //
   530  // Two heaps are used for sorting: the urgent heap (based on effective tip in the next
   531  // block) and the floating heap (based on gasFeeCap). Always the bigger heap is chosen for
   532  // eviction. Transactions evicted from the urgent heap are first demoted into the floating heap.
   533  // In some cases (during a congestion, when blocks are full) the urgent heap can provide
   534  // better candidates for inclusion while in other cases (at the top of the baseFee peak)
   535  // the floating heap is better. When baseFee is decreasing they behave similarly.
   536  type pricedList struct {
   537  	// Number of stale price points to (re-heap trigger).
   538  	stales atomic.Int64
   539  
   540  	all              *lookup    // Pointer to the map of all transactions
   541  	urgent, floating priceHeap  // Heaps of prices of all the stored **remote** transactions
   542  	reheapMu         sync.Mutex // Mutex asserts that only one routine is reheaping the list
   543  }
   544  
   545  const (
   546  	// urgentRatio : floatingRatio is the capacity ratio of the two queues
   547  	urgentRatio   = 4
   548  	floatingRatio = 1
   549  )
   550  
   551  // newPricedList creates a new price-sorted transaction heap.
   552  func newPricedList(all *lookup) *pricedList {
   553  	return &pricedList{
   554  		all: all,
   555  	}
   556  }
   557  
   558  // Put inserts a new transaction into the heap.
   559  func (l *pricedList) Put(tx *types.Transaction, local bool) {
   560  	if local {
   561  		return
   562  	}
   563  	// Insert every new transaction to the urgent heap first; Discard will balance the heaps
   564  	heap.Push(&l.urgent, tx)
   565  }
   566  
   567  // Removed notifies the prices transaction list that an old transaction dropped
   568  // from the pool. The list will just keep a counter of stale objects and update
   569  // the heap if a large enough ratio of transactions go stale.
   570  func (l *pricedList) Removed(count int) {
   571  	// Bump the stale counter, but exit if still too low (< 25%)
   572  	stales := l.stales.Add(int64(count))
   573  	if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 {
   574  		return
   575  	}
   576  	// Seems we've reached a critical number of stale transactions, reheap
   577  	l.Reheap()
   578  }
   579  
   580  // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
   581  // lowest priced (remote) transaction currently being tracked.
   582  func (l *pricedList) Underpriced(tx *types.Transaction) bool {
   583  	// Note: with two queues, being underpriced is defined as being worse than the worst item
   584  	// in all non-empty queues if there is any. If both queues are empty then nothing is underpriced.
   585  	return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) &&
   586  		(l.underpricedFor(&l.floating, tx) || len(l.floating.list) == 0) &&
   587  		(len(l.urgent.list) != 0 || len(l.floating.list) != 0)
   588  }
   589  
   590  // underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
   591  // lowest priced (remote) transaction in the given heap.
   592  func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
   593  	// Discard stale price points if found at the heap start
   594  	for len(h.list) > 0 {
   595  		head := h.list[0]
   596  		if l.all.GetRemote(head.Hash()) == nil { // Removed or migrated
   597  			l.stales.Add(-1)
   598  			heap.Pop(h)
   599  			continue
   600  		}
   601  		break
   602  	}
   603  	// Check if the transaction is underpriced or not
   604  	if len(h.list) == 0 {
   605  		return false // There is no remote transaction at all.
   606  	}
   607  	// If the remote transaction is even cheaper than the
   608  	// cheapest one tracked locally, reject it.
   609  	return h.cmp(h.list[0], tx) >= 0
   610  }
   611  
   612  // Discard finds a number of most underpriced transactions, removes them from the
   613  // priced list and returns them for further removal from the entire pool.
   614  // If noPending is set to true, we will only consider the floating list
   615  //
   616  // Note local transaction won't be considered for eviction.
   617  func (l *pricedList) Discard(slots int, force bool) (types.Transactions, bool) {
   618  	drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
   619  	for slots > 0 {
   620  		if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio {
   621  			// Discard stale transactions if found during cleanup
   622  			tx := heap.Pop(&l.urgent).(*types.Transaction)
   623  			if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
   624  				l.stales.Add(-1)
   625  				continue
   626  			}
   627  			// Non stale transaction found, move to floating heap
   628  			heap.Push(&l.floating, tx)
   629  		} else {
   630  			if len(l.floating.list) == 0 {
   631  				// Stop if both heaps are empty
   632  				break
   633  			}
   634  			// Discard stale transactions if found during cleanup
   635  			tx := heap.Pop(&l.floating).(*types.Transaction)
   636  			if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
   637  				l.stales.Add(-1)
   638  				continue
   639  			}
   640  			// Non stale transaction found, discard it
   641  			drop = append(drop, tx)
   642  			slots -= numSlots(tx)
   643  		}
   644  	}
   645  	// If we still can't make enough room for the new transaction
   646  	if slots > 0 && !force {
   647  		for _, tx := range drop {
   648  			heap.Push(&l.urgent, tx)
   649  		}
   650  		return nil, false
   651  	}
   652  	return drop, true
   653  }
   654  
   655  // Reheap forcibly rebuilds the heap based on the current remote transaction set.
   656  func (l *pricedList) Reheap() {
   657  	l.reheapMu.Lock()
   658  	defer l.reheapMu.Unlock()
   659  	start := time.Now()
   660  	l.stales.Store(0)
   661  	l.urgent.list = make([]*types.Transaction, 0, l.all.RemoteCount())
   662  	l.all.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
   663  		l.urgent.list = append(l.urgent.list, tx)
   664  		return true
   665  	}, false, true) // Only iterate remotes
   666  	heap.Init(&l.urgent)
   667  
   668  	// balance out the two heaps by moving the worse half of transactions into the
   669  	// floating heap
   670  	// Note: Discard would also do this before the first eviction but Reheap can do
   671  	// is more efficiently. Also, Underpriced would work suboptimally the first time
   672  	// if the floating queue was empty.
   673  	floatingCount := len(l.urgent.list) * floatingRatio / (urgentRatio + floatingRatio)
   674  	l.floating.list = make([]*types.Transaction, floatingCount)
   675  	for i := 0; i < floatingCount; i++ {
   676  		l.floating.list[i] = heap.Pop(&l.urgent).(*types.Transaction)
   677  	}
   678  	heap.Init(&l.floating)
   679  	reheapTimer.Update(time.Since(start))
   680  }
   681  
   682  // SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
   683  // necessary to call right before SetBaseFee when processing a new block.
   684  func (l *pricedList) SetBaseFee(baseFee *big.Int) {
   685  	l.urgent.baseFee = baseFee
   686  	l.Reheap()
   687  }