github.com/phillinzzz/newBsc@v1.1.6/core/tx_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 core
    18  
    19  import (
    20  	"container/heap"
    21  	"math"
    22  	"math/big"
    23  	"sort"
    24  	"sync"
    25  
    26  	"github.com/phillinzzz/newBsc/common"
    27  	"github.com/phillinzzz/newBsc/core/types"
    28  )
    29  
    30  var txSortedMapPool = sync.Pool{
    31  	New: func() interface{} {
    32  		return make(types.Transactions, 0, 10)
    33  	},
    34  }
    35  
    36  // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
    37  // retrieving sorted transactions from the possibly gapped future queue.
    38  type nonceHeap []uint64
    39  
    40  func (h nonceHeap) Len() int           { return len(h) }
    41  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
    42  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    43  
    44  func (h *nonceHeap) Push(x interface{}) {
    45  	*h = append(*h, x.(uint64))
    46  }
    47  
    48  func (h *nonceHeap) Pop() interface{} {
    49  	old := *h
    50  	n := len(old)
    51  	x := old[n-1]
    52  	*h = old[0 : n-1]
    53  	return x
    54  }
    55  
    56  // txSortedMap is a nonce->transaction hash map with a heap based index to allow
    57  // iterating over the contents in a nonce-incrementing way.
    58  type txSortedMap struct {
    59  	items map[uint64]*types.Transaction // Hash map storing the transaction data
    60  	index *nonceHeap                    // Heap of nonces of all the stored transactions (non-strict mode)
    61  	cache types.Transactions            // Cache of the transactions already sorted
    62  }
    63  
    64  // newTxSortedMap creates a new nonce-sorted transaction map.
    65  func newTxSortedMap() *txSortedMap {
    66  	return &txSortedMap{
    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 *txSortedMap) 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 *txSortedMap) Put(tx *types.Transaction) {
    80  	nonce := tx.Nonce()
    81  	if m.items[nonce] == nil {
    82  		heap.Push(m.index, nonce)
    83  	}
    84  	if m.cache != nil {
    85  		txSortedMapPool.Put(m.cache)
    86  	}
    87  	m.items[nonce], m.cache = tx, nil
    88  }
    89  
    90  // Forward removes all transactions from the map with a nonce lower than the
    91  // provided threshold. Every removed transaction is returned for any post-removal
    92  // maintenance.
    93  func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
    94  	var removed types.Transactions
    95  
    96  	// Pop off heap items until the threshold is reached
    97  	for m.index.Len() > 0 && (*m.index)[0] < threshold {
    98  		nonce := heap.Pop(m.index).(uint64)
    99  		removed = append(removed, m.items[nonce])
   100  		delete(m.items, nonce)
   101  	}
   102  	// If we had a cached order, shift the front
   103  	if m.cache != nil {
   104  		m.cache = m.cache[len(removed):]
   105  	}
   106  	return removed
   107  }
   108  
   109  // Filter iterates over the list of transactions and removes all of them for which
   110  // the specified function evaluates to true.
   111  // Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
   112  // If you want to do several consecutive filterings, it's therefore better to first
   113  // do a .filter(func1) followed by .Filter(func2) or reheap()
   114  func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
   115  	removed := m.filter(filter)
   116  	// If transactions were removed, the heap and cache are ruined
   117  	if len(removed) > 0 {
   118  		m.reheap()
   119  	}
   120  	return removed
   121  }
   122  
   123  func (m *txSortedMap) reheap() {
   124  	*m.index = make([]uint64, 0, len(m.items))
   125  	for nonce := range m.items {
   126  		*m.index = append(*m.index, nonce)
   127  	}
   128  	heap.Init(m.index)
   129  	m.cache = nil
   130  }
   131  
   132  // filter is identical to Filter, but **does not** regenerate the heap. This method
   133  // should only be used if followed immediately by a call to Filter or reheap()
   134  func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
   135  	var removed types.Transactions
   136  
   137  	// Collect all the transactions to filter out
   138  	for nonce, tx := range m.items {
   139  		if filter(tx) {
   140  			removed = append(removed, tx)
   141  			delete(m.items, nonce)
   142  		}
   143  	}
   144  	if len(removed) > 0 {
   145  		if m.cache != nil {
   146  			txSortedMapPool.Put(m.cache)
   147  			m.cache = nil
   148  		}
   149  	}
   150  	return removed
   151  }
   152  
   153  // Cap places a hard limit on the number of items, returning all transactions
   154  // exceeding that limit.
   155  func (m *txSortedMap) Cap(threshold int) types.Transactions {
   156  	// Short circuit if the number of items is under the limit
   157  	if len(m.items) <= threshold {
   158  		return nil
   159  	}
   160  	// Otherwise gather and drop the highest nonce'd transactions
   161  	var drops types.Transactions
   162  
   163  	sort.Sort(*m.index)
   164  	for size := len(m.items); size > threshold; size-- {
   165  		drops = append(drops, m.items[(*m.index)[size-1]])
   166  		delete(m.items, (*m.index)[size-1])
   167  	}
   168  	*m.index = (*m.index)[:threshold]
   169  	heap.Init(m.index)
   170  
   171  	// If we had a cache, shift the back
   172  	if m.cache != nil {
   173  		m.cache = m.cache[:len(m.cache)-len(drops)]
   174  	}
   175  	return drops
   176  }
   177  
   178  // Remove deletes a transaction from the maintained map, returning whether the
   179  // transaction was found.
   180  func (m *txSortedMap) Remove(nonce uint64) bool {
   181  	// Short circuit if no transaction is present
   182  	_, ok := m.items[nonce]
   183  	if !ok {
   184  		return false
   185  	}
   186  	// Otherwise delete the transaction and fix the heap index
   187  	for i := 0; i < m.index.Len(); i++ {
   188  		if (*m.index)[i] == nonce {
   189  			heap.Remove(m.index, i)
   190  			break
   191  		}
   192  	}
   193  	delete(m.items, nonce)
   194  	if m.cache != nil {
   195  		txSortedMapPool.Put(m.cache)
   196  		m.cache = nil
   197  	}
   198  
   199  	return true
   200  }
   201  
   202  // Ready retrieves a sequentially increasing list of transactions starting at the
   203  // provided nonce that is ready for processing. The returned transactions will be
   204  // removed from the list.
   205  //
   206  // Note, all transactions with nonces lower than start will also be returned to
   207  // prevent getting into and invalid state. This is not something that should ever
   208  // happen but better to be self correcting than failing!
   209  func (m *txSortedMap) Ready(start uint64) types.Transactions {
   210  	// Short circuit if no transactions are available
   211  	if m.index.Len() == 0 || (*m.index)[0] > start {
   212  		return nil
   213  	}
   214  	// Otherwise start accumulating incremental transactions
   215  	var ready types.Transactions
   216  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   217  		ready = append(ready, m.items[next])
   218  		delete(m.items, next)
   219  		heap.Pop(m.index)
   220  	}
   221  	if m.cache != nil {
   222  		txSortedMapPool.Put(m.cache)
   223  		m.cache = nil
   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  func (m *txSortedMap) flatten() types.Transactions {
   235  	// If the sorting was not cached yet, create and cache it
   236  	if m.cache == nil {
   237  		cache := txSortedMapPool.Get()
   238  		if cache != nil {
   239  			m.cache = cache.(types.Transactions)
   240  			m.cache = m.cache[:0]
   241  		} else {
   242  			m.cache = make(types.Transactions, 0, len(m.items))
   243  		}
   244  		for _, tx := range m.items {
   245  			m.cache = append(m.cache, tx)
   246  		}
   247  		sort.Sort(types.TxByNonce(m.cache))
   248  	}
   249  	return m.cache
   250  }
   251  
   252  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   253  // sorted internal representation. The result of the sorting is cached in case
   254  // it's requested again before any modifications are made to the contents.
   255  func (m *txSortedMap) Flatten() types.Transactions {
   256  	// Copy the cache to prevent accidental modifications
   257  	cache := m.flatten()
   258  	txs := make(types.Transactions, len(cache))
   259  	copy(txs, cache)
   260  	return txs
   261  }
   262  
   263  // LastElement returns the last element of a flattened list, thus, the
   264  // transaction with the highest nonce
   265  func (m *txSortedMap) LastElement() *types.Transaction {
   266  	cache := m.flatten()
   267  	return cache[len(cache)-1]
   268  }
   269  
   270  // txList is a "list" of transactions belonging to an account, sorted by account
   271  // nonce. The same type can be used both for storing contiguous transactions for
   272  // the executable/pending queue; and for storing gapped transactions for the non-
   273  // executable/future queue, with minor behavioral changes.
   274  type txList struct {
   275  	strict bool         // Whether nonces are strictly continuous or not
   276  	txs    *txSortedMap // Heap indexed sorted hash map of the transactions
   277  
   278  	costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
   279  	gascap  uint64   // Gas limit of the highest spending transaction (reset only if exceeds block limit)
   280  }
   281  
   282  // newTxList create a new transaction list for maintaining nonce-indexable fast,
   283  // gapped, sortable transaction lists.
   284  func newTxList(strict bool) *txList {
   285  	return &txList{
   286  		strict:  strict,
   287  		txs:     newTxSortedMap(),
   288  		costcap: new(big.Int),
   289  	}
   290  }
   291  
   292  // Overlaps returns whether the transaction specified has the same nonce as one
   293  // already contained within the list.
   294  func (l *txList) Overlaps(tx *types.Transaction) bool {
   295  	return l.txs.Get(tx.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 *txList) 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  		// threshold = oldGP * (100 + priceBump) / 100
   308  		a := big.NewInt(100 + int64(priceBump))
   309  		a = a.Mul(a, old.GasPrice())
   310  		b := big.NewInt(100)
   311  		threshold := a.Div(a, b)
   312  		// Have to ensure that the new gas price is higher than the old gas
   313  		// price as well as checking the percentage threshold to ensure that
   314  		// this is accurate for low (Wei-level) gas price replacements
   315  		if old.GasPriceCmp(tx) >= 0 || tx.GasPriceIntCmp(threshold) < 0 {
   316  			return false, nil
   317  		}
   318  	}
   319  	// Otherwise overwrite the old transaction with the current one
   320  	l.txs.Put(tx)
   321  	if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
   322  		l.costcap = cost
   323  	}
   324  	if gas := tx.Gas(); l.gascap < gas {
   325  		l.gascap = gas
   326  	}
   327  	return true, old
   328  }
   329  
   330  // Forward removes all transactions from the list with a nonce lower than the
   331  // provided threshold. Every removed transaction is returned for any post-removal
   332  // maintenance.
   333  func (l *txList) Forward(threshold uint64) types.Transactions {
   334  	return l.txs.Forward(threshold)
   335  }
   336  
   337  // Filter removes all transactions from the list with a cost or gas limit higher
   338  // than the provided thresholds. Every removed transaction is returned for any
   339  // post-removal maintenance. Strict-mode invalidated transactions are also
   340  // returned.
   341  //
   342  // This method uses the cached costcap and gascap to quickly decide if there's even
   343  // a point in calculating all the costs or if the balance covers all. If the threshold
   344  // is lower than the costgas cap, the caps will be reset to a new high after removing
   345  // the newly invalidated transactions.
   346  func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
   347  	// If all transactions are below the threshold, short circuit
   348  	if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
   349  		return nil, nil
   350  	}
   351  	l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
   352  	l.gascap = gasLimit
   353  
   354  	// Filter out all the transactions above the account's funds
   355  	removed := l.txs.Filter(func(tx *types.Transaction) bool {
   356  		return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit) > 0
   357  	})
   358  
   359  	if len(removed) == 0 {
   360  		return nil, nil
   361  	}
   362  	var invalids types.Transactions
   363  	// If the list was strict, filter anything above the lowest nonce
   364  	if l.strict {
   365  		lowest := uint64(math.MaxUint64)
   366  		for _, tx := range removed {
   367  			if nonce := tx.Nonce(); lowest > nonce {
   368  				lowest = nonce
   369  			}
   370  		}
   371  		invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
   372  	}
   373  	l.txs.reheap()
   374  	return removed, invalids
   375  }
   376  
   377  // Cap places a hard limit on the number of items, returning all transactions
   378  // exceeding that limit.
   379  func (l *txList) Cap(threshold int) types.Transactions {
   380  	return l.txs.Cap(threshold)
   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 *txList) 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  	// In strict mode, filter out non-executable transactions
   393  	if l.strict {
   394  		return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce })
   395  	}
   396  	return true, nil
   397  }
   398  
   399  // Ready retrieves a sequentially increasing list of transactions starting at the
   400  // provided nonce that is ready for processing. The returned transactions will be
   401  // removed from the list.
   402  //
   403  // Note, all transactions with nonces lower than start will also be returned to
   404  // prevent getting into and invalid state. This is not something that should ever
   405  // happen but better to be self correcting than failing!
   406  func (l *txList) Ready(start uint64) types.Transactions {
   407  	return l.txs.Ready(start)
   408  }
   409  
   410  // Len returns the length of the transaction list.
   411  func (l *txList) Len() int {
   412  	return len(l.txs.items)
   413  }
   414  
   415  // Empty returns whether the list of transactions is empty or not.
   416  func (l *txList) Empty() bool {
   417  	return l.Len() == 0
   418  }
   419  
   420  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   421  // sorted internal representation. The result of the sorting is cached in case
   422  // it's requested again before any modifications are made to the contents.
   423  func (l *txList) Flatten() types.Transactions {
   424  	return l.txs.Flatten()
   425  }
   426  
   427  // LastElement returns the last element of a flattened list, thus, the
   428  // transaction with the highest nonce
   429  func (l *txList) LastElement() *types.Transaction {
   430  	return l.txs.LastElement()
   431  }
   432  
   433  // priceHeap is a heap.Interface implementation over transactions for retrieving
   434  // price-sorted transactions to discard when the pool fills up.
   435  type priceHeap []*types.Transaction
   436  
   437  func (h priceHeap) Len() int      { return len(h) }
   438  func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
   439  
   440  func (h priceHeap) Less(i, j int) bool {
   441  	// Sort primarily by price, returning the cheaper one
   442  	switch h[i].GasPriceCmp(h[j]) {
   443  	case -1:
   444  		return true
   445  	case 1:
   446  		return false
   447  	}
   448  	// If the prices match, stabilize via nonces (high nonce is worse)
   449  	return h[i].Nonce() > h[j].Nonce()
   450  }
   451  
   452  func (h *priceHeap) Push(x interface{}) {
   453  	*h = append(*h, x.(*types.Transaction))
   454  }
   455  
   456  func (h *priceHeap) Pop() interface{} {
   457  	old := *h
   458  	n := len(old)
   459  	x := old[n-1]
   460  	old[n-1] = nil
   461  	*h = old[0 : n-1]
   462  	return x
   463  }
   464  
   465  // txPricedList is a price-sorted heap to allow operating on transactions pool
   466  // contents in a price-incrementing way. It's built opon the all transactions
   467  // in txpool but only interested in the remote part. It means only remote transactions
   468  // will be considered for tracking, sorting, eviction, etc.
   469  type txPricedList struct {
   470  	all     *txLookup  // Pointer to the map of all transactions
   471  	remotes *priceHeap // Heap of prices of all the stored **remote** transactions
   472  	stales  int        // Number of stale price points to (re-heap trigger)
   473  }
   474  
   475  // newTxPricedList creates a new price-sorted transaction heap.
   476  func newTxPricedList(all *txLookup) *txPricedList {
   477  	return &txPricedList{
   478  		all:     all,
   479  		remotes: new(priceHeap),
   480  	}
   481  }
   482  
   483  // Put inserts a new transaction into the heap.
   484  func (l *txPricedList) Put(tx *types.Transaction, local bool) {
   485  	if local {
   486  		return
   487  	}
   488  	heap.Push(l.remotes, tx)
   489  }
   490  
   491  // Removed notifies the prices transaction list that an old transaction dropped
   492  // from the pool. The list will just keep a counter of stale objects and update
   493  // the heap if a large enough ratio of transactions go stale.
   494  func (l *txPricedList) Removed(count int) {
   495  	// Bump the stale counter, but exit if still too low (< 25%)
   496  	l.stales += count
   497  	if l.stales <= len(*l.remotes)/4 {
   498  		return
   499  	}
   500  	// Seems we've reached a critical number of stale transactions, reheap
   501  	l.Reheap()
   502  }
   503  
   504  // Cap finds all the transactions below the given price threshold, drops them
   505  // from the priced list and returns them for further removal from the entire pool.
   506  //
   507  // Note: only remote transactions will be considered for eviction.
   508  func (l *txPricedList) Cap(threshold *big.Int) types.Transactions {
   509  	drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
   510  	for len(*l.remotes) > 0 {
   511  		// Discard stale transactions if found during cleanup
   512  		cheapest := (*l.remotes)[0]
   513  		if l.all.GetRemote(cheapest.Hash()) == nil { // Removed or migrated
   514  			heap.Pop(l.remotes)
   515  			l.stales--
   516  			continue
   517  		}
   518  		// Stop the discards if we've reached the threshold
   519  		if cheapest.GasPriceIntCmp(threshold) >= 0 {
   520  			break
   521  		}
   522  		heap.Pop(l.remotes)
   523  		drop = append(drop, cheapest)
   524  	}
   525  	return drop
   526  }
   527  
   528  // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
   529  // lowest priced (remote) transaction currently being tracked.
   530  func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
   531  	// Discard stale price points if found at the heap start
   532  	for len(*l.remotes) > 0 {
   533  		head := []*types.Transaction(*l.remotes)[0]
   534  		if l.all.GetRemote(head.Hash()) == nil { // Removed or migrated
   535  			l.stales--
   536  			heap.Pop(l.remotes)
   537  			continue
   538  		}
   539  		break
   540  	}
   541  	// Check if the transaction is underpriced or not
   542  	if len(*l.remotes) == 0 {
   543  		return false // There is no remote transaction at all.
   544  	}
   545  	// If the remote transaction is even cheaper than the
   546  	// cheapest one tracked locally, reject it.
   547  	cheapest := []*types.Transaction(*l.remotes)[0]
   548  	return cheapest.GasPriceCmp(tx) >= 0
   549  }
   550  
   551  // Discard finds a number of most underpriced transactions, removes them from the
   552  // priced list and returns them for further removal from the entire pool.
   553  //
   554  // Note local transaction won't be considered for eviction.
   555  func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool) {
   556  	drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
   557  	for len(*l.remotes) > 0 && slots > 0 {
   558  		// Discard stale transactions if found during cleanup
   559  		tx := heap.Pop(l.remotes).(*types.Transaction)
   560  		if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
   561  			l.stales--
   562  			continue
   563  		}
   564  		// Non stale transaction found, discard it
   565  		drop = append(drop, tx)
   566  		slots -= numSlots(tx)
   567  	}
   568  	// If we still can't make enough room for the new transaction
   569  	if slots > 0 && !force {
   570  		for _, tx := range drop {
   571  			heap.Push(l.remotes, tx)
   572  		}
   573  		return nil, false
   574  	}
   575  	return drop, true
   576  }
   577  
   578  // Reheap forcibly rebuilds the heap based on the current remote transaction set.
   579  func (l *txPricedList) Reheap() {
   580  	reheap := make(priceHeap, 0, l.all.RemoteCount())
   581  
   582  	l.stales, l.remotes = 0, &reheap
   583  	l.all.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
   584  		*l.remotes = append(*l.remotes, tx)
   585  		return true
   586  	}, false, true) // Only iterate remotes
   587  	heap.Init(l.remotes)
   588  }