github.com/klaytn/klaytn@v1.12.1/blockchain/tx_list.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2016 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from core/tx_list.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package blockchain
    22  
    23  import (
    24  	"container/heap"
    25  	"math"
    26  	"math/big"
    27  	"sort"
    28  
    29  	"github.com/klaytn/klaytn/blockchain/types"
    30  	"github.com/klaytn/klaytn/common"
    31  )
    32  
    33  // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
    34  // retrieving sorted transactions from the possibly gapped future queue.
    35  type nonceHeap []uint64
    36  
    37  func (h nonceHeap) Len() int           { return len(h) }
    38  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
    39  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    40  
    41  func (h *nonceHeap) Push(x interface{}) {
    42  	*h = append(*h, x.(uint64))
    43  }
    44  
    45  func (h *nonceHeap) Pop() interface{} {
    46  	old := *h
    47  	n := len(old)
    48  	x := old[n-1]
    49  	*h = old[0 : n-1]
    50  	return x
    51  }
    52  
    53  // txSortedMap 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 txSortedMap 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  // newTxSortedMap creates a new nonce-sorted transaction map.
    62  func newTxSortedMap() *txSortedMap {
    63  	return &txSortedMap{
    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 *txSortedMap) 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 *txSortedMap) 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 *txSortedMap) 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  func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
   106  	var removed types.Transactions
   107  
   108  	// Collect all the transactions to filter out
   109  	for nonce, tx := range m.items {
   110  		if filter(tx) {
   111  			removed = append(removed, tx)
   112  			delete(m.items, nonce)
   113  		}
   114  	}
   115  	// If transactions were removed, the heap and cache are ruined
   116  	if len(removed) > 0 {
   117  		*m.index = make([]uint64, 0, len(m.items))
   118  		for nonce := range m.items {
   119  			*m.index = append(*m.index, nonce)
   120  		}
   121  		heap.Init(m.index)
   122  
   123  		m.cache = nil
   124  	}
   125  	return removed
   126  }
   127  
   128  // Cap places a hard limit on the number of items, returning all transactions
   129  // exceeding that limit.
   130  func (m *txSortedMap) Cap(threshold int) types.Transactions {
   131  	// Short circuit if the number of items is under the limit
   132  	if len(m.items) <= threshold {
   133  		return nil
   134  	}
   135  	// Otherwise gather and drop the highest nonce'd transactions
   136  	var drops types.Transactions
   137  
   138  	sort.Sort(*m.index)
   139  	for size := len(m.items); size > threshold; size-- {
   140  		drops = append(drops, m.items[(*m.index)[size-1]])
   141  		delete(m.items, (*m.index)[size-1])
   142  	}
   143  	*m.index = (*m.index)[:threshold]
   144  	heap.Init(m.index)
   145  
   146  	// If we had a cache, shift the back
   147  	if m.cache != nil {
   148  		m.cache = m.cache[:len(m.cache)-len(drops)]
   149  	}
   150  	return drops
   151  }
   152  
   153  // Remove deletes a transaction from the maintained map, returning whether the
   154  // transaction was found.
   155  func (m *txSortedMap) Remove(nonce uint64) bool {
   156  	// Short circuit if no transaction is present
   157  	_, ok := m.items[nonce]
   158  	if !ok {
   159  		return false
   160  	}
   161  	// Otherwise delete the transaction and fix the heap index
   162  	for i := 0; i < m.index.Len(); i++ {
   163  		if (*m.index)[i] == nonce {
   164  			heap.Remove(m.index, i)
   165  			break
   166  		}
   167  	}
   168  	delete(m.items, nonce)
   169  	m.cache = nil
   170  
   171  	return true
   172  }
   173  
   174  // Ready retrieves a sequentially increasing list of transactions starting at the
   175  // provided nonce that is ready for processing. The returned transactions will be
   176  // removed from the list.
   177  //
   178  // Note, all transactions with nonces lower than start will also be returned to
   179  // prevent getting into and invalid state. This is not something that should ever
   180  // happen but better to be self correcting than failing!
   181  func (m *txSortedMap) Ready(start uint64) types.Transactions {
   182  	// Short circuit if no transactions are available
   183  	if m.index.Len() == 0 || (*m.index)[0] > start {
   184  		return nil
   185  	}
   186  	// Otherwise start accumulating incremental transactions
   187  	var ready types.Transactions
   188  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   189  		ready = append(ready, m.items[next])
   190  		delete(m.items, next)
   191  		heap.Pop(m.index)
   192  	}
   193  	m.cache = nil
   194  
   195  	return ready
   196  }
   197  
   198  // ReadyWithGasPrice retrieves a sequentially increasing list of transactions that greater than or
   199  // equal to the given baseFee starting at the provided nonce that is ready for processing.
   200  // If there is a transaction lower than the baseFee during the search, only previously collected transactions
   201  // are returned. The returned transactions will be removed from the list.
   202  //
   203  // Note, all transactions with nonces lower than start will also be returned to
   204  // prevent getting into and invalid state. This is not something that should ever
   205  // happen but better to be self correcting than failing!
   206  func (m *txSortedMap) ReadyWithGasPrice(start uint64, baseFee *big.Int) types.Transactions {
   207  	// Short circuit if no transactions are available
   208  	if m.index.Len() == 0 || (*m.index)[0] > start {
   209  		return nil
   210  	}
   211  	// Otherwise start accumulating incremental transactions
   212  	ready := make(types.Transactions, 0, m.index.Len())
   213  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   214  		if m.items[next].GasPrice().Cmp(baseFee) < 0 {
   215  			break
   216  		}
   217  		ready = append(ready, m.items[next])
   218  		delete(m.items, next)
   219  		heap.Pop(m.index)
   220  	}
   221  	// If we had a cached order, shift the front
   222  	if m.cache != nil {
   223  		m.cache = m.cache[len(ready):]
   224  	}
   225  
   226  	return ready
   227  }
   228  
   229  // Len returns the length of the transaction map.
   230  func (m *txSortedMap) Len() int {
   231  	return len(m.items)
   232  }
   233  
   234  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   235  // sorted internal representation. The result of the sorting is cached in case
   236  // it's requested again before any modifications are made to the contents.
   237  func (m *txSortedMap) Flatten() types.Transactions {
   238  	return m.FlattenByCount(0)
   239  }
   240  
   241  func (m *txSortedMap) FlattenByCount(count int64) types.Transactions {
   242  	// If the sorting was not cached yet, create and cache it
   243  	if m.cache == nil {
   244  		m.cache = make(types.Transactions, 0, len(m.items))
   245  		for _, tx := range m.items {
   246  			m.cache = append(m.cache, tx)
   247  		}
   248  		sort.Sort(types.TxByNonce(m.cache))
   249  	}
   250  	txLen := int64(len(m.cache))
   251  	if count != 0 && txLen > count {
   252  		txLen = count
   253  	}
   254  	// Copy the cache to prevent accidental modifications
   255  	txs := make(types.Transactions, txLen)
   256  	copy(txs, m.cache)
   257  	return txs
   258  }
   259  
   260  // CachedTxsFlattenByCount returns a nonce-sorted slice including at most
   261  // a requested number of cached in case it's requested again before any
   262  // modifications are made to the contents.
   263  func (m *txSortedMap) CachedTxsFlattenByCount(count int) types.Transactions {
   264  	if count <= 0 {
   265  		return nil
   266  	}
   267  	// If the sorting was not cached yet, create and cache it
   268  	if m.cache == nil {
   269  		m.cache = make(types.Transactions, 0, len(m.items))
   270  		for _, tx := range m.items {
   271  			m.cache = append(m.cache, tx)
   272  		}
   273  		sort.Sort(types.TxByNonce(m.cache))
   274  	}
   275  	txLen := len(m.cache)
   276  	if count != 0 && txLen > count {
   277  		txLen = count
   278  	}
   279  	return m.cache[:txLen]
   280  }
   281  
   282  // txList is a "list" of transactions belonging to an account, sorted by account
   283  // nonce. The same type can be used both for storing contiguous transactions for
   284  // the executable/pending queue; and for storing gapped transactions for the non-
   285  // executable/future queue, with minor behavioral changes.
   286  type txList struct {
   287  	strict bool         // Whether nonces are strictly continuous or not
   288  	txs    *txSortedMap // Heap indexed sorted hash map of the transactions
   289  }
   290  
   291  // newTxList create a new transaction list for maintaining nonce-indexable fast,
   292  // gapped, sortable transaction lists.
   293  func newTxList(strict bool) *txList {
   294  	return &txList{
   295  		strict: strict,
   296  		txs:    newTxSortedMap(),
   297  	}
   298  }
   299  
   300  // Overlaps returns whether the transaction specified has the same nonce as one
   301  // already contained within the list.
   302  func (l *txList) Overlaps(tx *types.Transaction) bool {
   303  	return l.txs.Get(tx.Nonce()) != nil
   304  }
   305  
   306  // Add tries to insert a new transaction into the list, returning whether the
   307  // transaction was accepted, and if yes, any previous transaction it replaced.
   308  //
   309  // If the new transaction is accepted into the list, the lists' cost and gas
   310  // thresholds are also potentially updated.
   311  func (l *txList) Add(tx *types.Transaction, priceBump uint64, magmaHardforked bool) (bool, *types.Transaction) {
   312  	// If there's an older better transaction, abort
   313  	old := l.txs.Get(tx.Nonce())
   314  	if old != nil {
   315  		// If tx is CancelTransaction, replace it even thought tx has lower gasPrice than previous tx.
   316  		if tx.Type().IsCancelTransaction() {
   317  			logger.Trace("New tx is a cancel transaction. replace it!", "old", old.String(), "new", tx.String())
   318  		} else if magmaHardforked {
   319  			if old.GasPrice().Cmp(tx.GasPrice()) >= 0 {
   320  				// If gas price of older is bigger than newer, abort.
   321  				logger.Trace("already nonce exist and the gasprice is lower then older", "nonce", tx.Nonce(), "with gasprice", old.GasPrice(), "priceBump", priceBump, "new tx.gasprice", tx.GasPrice())
   322  				return false, nil
   323  			}
   324  			// Otherwise overwrite the old transaction with the current one.
   325  			logger.Trace("The transaction was substituted by competitive gas price", "old", old.String(), "new", tx.String())
   326  		} else {
   327  			logger.Trace("already nonce exist", "nonce", tx.Nonce(), "with gasprice", old.GasPrice(), "priceBump", priceBump, "new tx.gasprice", tx.GasPrice())
   328  			return false, nil
   329  		}
   330  	}
   331  
   332  	l.txs.Put(tx)
   333  	return true, old
   334  }
   335  
   336  // Forward removes all transactions from the list with a nonce lower than the
   337  // provided threshold. Every removed transaction is returned for any post-removal
   338  // maintenance.
   339  func (l *txList) Forward(threshold uint64) types.Transactions {
   340  	return l.txs.Forward(threshold)
   341  }
   342  
   343  // Filter removes all transactions from the list with a cost higher
   344  // than the provided thresholds. Every removed transaction is returned for any
   345  // post-removal maintenance. Strict-mode invalidated transactions are also
   346  // returned.
   347  //
   348  // This method uses the cached costcap to quickly decide if there's even
   349  // a point in calculating all the costs or if the balance covers all. If the threshold
   350  // is lower than the costcap, the caps will be reset to a new high after removing
   351  // the newly invalidated transactions.
   352  func (l *txList) Filter(sender common.Address, pool *TxPool) (types.Transactions, types.Transactions) {
   353  	// Filter out all the transactions above the account's funds
   354  	removed := l.txs.Filter(func(tx *types.Transaction) bool {
   355  		senderBalance := pool.getBalance(sender)
   356  		// Drop a tx if it is marked as un-executable on block generation process.
   357  		if tx.IsMarkedUnexecutable() {
   358  			return true
   359  		}
   360  		// Since there are mutable values such as accountKey in the state, a tx can be invalidated with the state change.
   361  		if tx.ValidateMutableValue(pool.currentState, pool.signer, pool.currentBlockNumber) != nil {
   362  			return true
   363  		}
   364  		// In case of fee-delegated transactions, the comparison value should consider tx fee and fee ratio.
   365  		if tx.IsFeeDelegatedTransaction() {
   366  			feePayer, _ := tx.FeePayer()
   367  			feePayerBalance := pool.getBalance(feePayer)
   368  			feeRatio, isRatioTx := tx.FeeRatio()
   369  
   370  			// Handling the special case when the sender and fee payer are the same.
   371  			if sender == feePayer {
   372  				return senderBalance.Cmp(tx.Cost()) < 0
   373  			}
   374  			if isRatioTx {
   375  				feeByFeePayer, feeBySender := types.CalcFeeWithRatio(feeRatio, tx.Fee())
   376  				return senderBalance.Cmp(new(big.Int).Add(tx.Value(), feeBySender)) < 0 || feePayerBalance.Cmp(feeByFeePayer) < 0
   377  			} else {
   378  				return senderBalance.Cmp(tx.Value()) < 0 || feePayerBalance.Cmp(tx.Fee()) < 0
   379  			}
   380  		}
   381  		// For other transactions, all tx cost should be payable by the sender.
   382  		return senderBalance.Cmp(tx.Cost()) < 0
   383  	})
   384  
   385  	// If the list was strict, filter anything above the lowest nonce
   386  	var invalids types.Transactions
   387  
   388  	if l.strict && len(removed) > 0 {
   389  		lowest := uint64(math.MaxUint64)
   390  		for _, tx := range removed {
   391  			if nonce := tx.Nonce(); lowest > nonce {
   392  				lowest = nonce
   393  			}
   394  		}
   395  		invalids = l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
   396  	}
   397  	return removed, invalids
   398  }
   399  
   400  // FilterUnexecutable removes all transactions marked as unexecutable.
   401  func (l *txList) FilterUnexecutable() (types.Transactions, types.Transactions) {
   402  	removed := l.txs.Filter(func(tx *types.Transaction) bool {
   403  		// Drop a tx if it is marked as un-executable on block generation process.
   404  		if tx.IsMarkedUnexecutable() {
   405  			return true
   406  		}
   407  		return false
   408  	})
   409  
   410  	// If the list was strict, filter anything above the lowest nonce
   411  	var invalids types.Transactions
   412  
   413  	if l.strict && len(removed) > 0 {
   414  		lowest := uint64(math.MaxUint64)
   415  		for _, tx := range removed {
   416  			if nonce := tx.Nonce(); lowest > nonce {
   417  				lowest = nonce
   418  			}
   419  		}
   420  		invalids = l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
   421  	}
   422  	return removed, invalids
   423  }
   424  
   425  // Cap places a hard limit on the number of items, returning all transactions
   426  // exceeding that limit.
   427  func (l *txList) Cap(threshold int) types.Transactions {
   428  	return l.txs.Cap(threshold)
   429  }
   430  
   431  // Remove deletes a transaction from the maintained list, returning whether the
   432  // transaction was found, and also returning any transaction invalidated due to
   433  // the deletion (strict mode only).
   434  func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
   435  	// Remove the transaction from the set
   436  	nonce := tx.Nonce()
   437  	if removed := l.txs.Remove(nonce); !removed {
   438  		return false, nil
   439  	}
   440  	// In strict mode, filter out non-executable transactions
   441  	if l.strict {
   442  		return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce })
   443  	}
   444  	return true, nil
   445  }
   446  
   447  // Ready retrieves a sequentially increasing list of transactions starting at the
   448  // provided nonce that is ready for processing. The returned transactions will be
   449  // removed from the list.
   450  //
   451  // Note, all transactions with nonces lower than start will also be returned to
   452  // prevent getting into and invalid state. This is not something that should ever
   453  // happen but better to be self correcting than failing!
   454  func (l *txList) Ready(start uint64) types.Transactions {
   455  	return l.txs.Ready(start)
   456  }
   457  
   458  // ReadyWithGasPrice retrieves a sequentially increasing list of transactions that greater than or
   459  // equal to the given baseFee starting at the provided nonce that is ready for processing.
   460  // If there is a transaction lower than the baseFee during the search, only previously collected transactions
   461  // are returned. The returned transactions will be removed from the list.
   462  //
   463  // Note, all transactions with nonces lower than start will also be returned to
   464  // prevent getting into and invalid state. This is not something that should ever
   465  // happen but better to be self correcting than failing!
   466  func (l *txList) ReadyWithGasPrice(start uint64, baseFee *big.Int) types.Transactions {
   467  	return l.txs.ReadyWithGasPrice(start, baseFee)
   468  }
   469  
   470  // Len returns the length of the transaction list.
   471  func (l *txList) Len() int {
   472  	return l.txs.Len()
   473  }
   474  
   475  // Empty returns whether the list of transactions is empty or not.
   476  func (l *txList) Empty() bool {
   477  	return l.Len() == 0
   478  }
   479  
   480  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   481  // sorted internal representation. The result of the sorting is cached in case
   482  // it's requested again before any modifications are made to the contents.
   483  func (l *txList) Flatten() types.Transactions {
   484  	return l.txs.Flatten()
   485  }
   486  
   487  func (l *txList) FlattenByCount(count int64) types.Transactions {
   488  	return l.txs.FlattenByCount(count)
   489  }
   490  
   491  func (l *txList) CachedTxsFlattenByCount(count int) types.Transactions {
   492  	return l.txs.CachedTxsFlattenByCount(count)
   493  }
   494  
   495  // priceHeap is a heap.Interface implementation over transactions for retrieving
   496  // price-sorted transactions to discard when the pool fills up.
   497  type priceHeap []*types.Transaction
   498  
   499  func (h priceHeap) Len() int      { return len(h) }
   500  func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
   501  
   502  func (h priceHeap) Less(i, j int) bool {
   503  	// Sort primarily by price, returning the cheaper one
   504  	switch h[i].GasPrice().Cmp(h[j].GasPrice()) {
   505  	case -1:
   506  		return true
   507  	case 1:
   508  		return false
   509  	}
   510  	// If the prices match, stabilize via nonces (high nonce is worse)
   511  	return h[i].Nonce() > h[j].Nonce()
   512  }
   513  
   514  func (h *priceHeap) Push(x interface{}) {
   515  	*h = append(*h, x.(*types.Transaction))
   516  }
   517  
   518  func (h *priceHeap) Pop() interface{} {
   519  	old := *h
   520  	n := len(old)
   521  	x := old[n-1]
   522  	*h = old[0 : n-1]
   523  	return x
   524  }
   525  
   526  // txPricedList is a price-sorted heap to allow operating on transactions pool
   527  // contents in a price-incrementing way.
   528  type txPricedList struct {
   529  	all    *txLookup  // Pointer to the map of all transactions
   530  	items  *priceHeap // Heap of prices of all the stored transactions
   531  	stales int        // Number of stale price points to (re-heap trigger)
   532  }
   533  
   534  // newTxPricedList creates a new price-sorted transaction heap.
   535  func newTxPricedList(all *txLookup) *txPricedList {
   536  	return &txPricedList{
   537  		all:   all,
   538  		items: new(priceHeap),
   539  	}
   540  }
   541  
   542  // Put inserts a new transaction into the heap.
   543  func (l *txPricedList) Put(tx *types.Transaction) {
   544  	heap.Push(l.items, tx)
   545  }
   546  
   547  // Removed notifies the prices transaction list that an old transaction dropped
   548  // from the pool. The list will just keep a counter of stale objects and update
   549  // the heap if a large enough ratio of transactions go stale.
   550  func (l *txPricedList) Removed() {
   551  	// Bump the stale counter, but exit if still too low (< 25%)
   552  	l.stales++
   553  	if l.stales <= len(*l.items)/4 {
   554  		return
   555  	}
   556  	// Seems we've reached a critical number of stale transactions, reheap
   557  	reheap := make(priceHeap, 0, l.all.Count())
   558  
   559  	l.stales, l.items = 0, &reheap
   560  	l.all.Range(func(hash common.Hash, tx *types.Transaction) bool {
   561  		*l.items = append(*l.items, tx)
   562  		return true
   563  	})
   564  	heap.Init(l.items)
   565  }
   566  
   567  // Cap finds all the transactions below the given price threshold, drops them
   568  // from the priced list and returs them for further removal from the entire pool.
   569  func (l *txPricedList) Cap(threshold *big.Int, local *accountSet) types.Transactions {
   570  	drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
   571  	save := make(types.Transactions, 0, 64)  // Local underpriced transactions to keep
   572  
   573  	for len(*l.items) > 0 {
   574  		// Discard stale transactions if found during cleanup
   575  		tx := heap.Pop(l.items).(*types.Transaction)
   576  		if l.all.Get(tx.Hash()) == nil {
   577  			l.stales--
   578  			continue
   579  		}
   580  		// Stop the discards if we've reached the threshold
   581  		if tx.GasPrice().Cmp(threshold) >= 0 {
   582  			save = append(save, tx)
   583  			break
   584  		}
   585  		// Non stale transaction found, discard unless local
   586  		if local.containsTx(tx) {
   587  			save = append(save, tx)
   588  		} else {
   589  			drop = append(drop, tx)
   590  		}
   591  	}
   592  	for _, tx := range save {
   593  		heap.Push(l.items, tx)
   594  	}
   595  	return drop
   596  }
   597  
   598  // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
   599  // lowest priced transaction currently being tracked.
   600  func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) bool {
   601  	// Local transactions cannot be underpriced
   602  	if local.containsTx(tx) {
   603  		return false
   604  	}
   605  	// Discard stale price points if found at the heap start
   606  	for len(*l.items) > 0 {
   607  		head := []*types.Transaction(*l.items)[0]
   608  		if l.all.Get(head.Hash()) == nil {
   609  			l.stales--
   610  			heap.Pop(l.items)
   611  			continue
   612  		}
   613  		break
   614  	}
   615  	// Check if the transaction is underpriced or not
   616  	if len(*l.items) == 0 {
   617  		logger.Error("Pricing query for empty pool") // This cannot happen, print to catch programming errors
   618  		return false
   619  	}
   620  	cheapest := []*types.Transaction(*l.items)[0]
   621  	return cheapest.GasPrice().Cmp(tx.GasPrice()) >= 0
   622  }
   623  
   624  // Discard finds a number of most underpriced transactions, removes them from the
   625  // priced list and returns them for further removal from the entire pool.
   626  func (l *txPricedList) Discard(slots int, local *accountSet) types.Transactions {
   627  	drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
   628  	save := make(types.Transactions, 0, 64)    // Local underpriced transactions to keep
   629  
   630  	for len(*l.items) > 0 && slots > 0 {
   631  		// Discard stale transactions if found during cleanup
   632  		tx := heap.Pop(l.items).(*types.Transaction)
   633  		if l.all.Get(tx.Hash()) == nil {
   634  			l.stales--
   635  			continue
   636  		}
   637  		// Non stale transaction found, discard unless local
   638  		if local.containsTx(tx) {
   639  			save = append(save, tx)
   640  		} else {
   641  			drop = append(drop, tx)
   642  			slots -= numSlots(tx)
   643  		}
   644  	}
   645  	for _, tx := range save {
   646  		heap.Push(l.items, tx)
   647  	}
   648  	return drop
   649  }