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