github.com/amazechain/amc@v0.1.3/internal/txspool/txs_list.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package txspool
    18  
    19  import (
    20  	"container/heap"
    21  	"github.com/amazechain/amc/common/transaction"
    22  	"github.com/amazechain/amc/common/types"
    23  	"github.com/holiman/uint256"
    24  	"math"
    25  	"sort"
    26  	"sync"
    27  	"sync/atomic"
    28  	"time"
    29  	"unsafe"
    30  )
    31  
    32  // addressByHeartbeat is an account address tagged with its last activity timestamp.
    33  type addressByHeartbeat struct {
    34  	address   types.Address
    35  	heartbeat time.Time
    36  }
    37  
    38  type addressesByHeartbeat []addressByHeartbeat
    39  
    40  func (a addressesByHeartbeat) Len() int           { return len(a) }
    41  func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) }
    42  func (a addressesByHeartbeat) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
    43  
    44  // accountSet is simply a set of addresses to check for existence, and a signer
    45  // capable of deriving addresses from transactions.
    46  type accountSet struct {
    47  	accounts map[types.Address]struct{}
    48  	cache    *[]types.Address
    49  }
    50  
    51  // newAccountSet creates a new address set with an associated signer for sender
    52  // derivations.
    53  func newAccountSet(addrs ...types.Address) *accountSet {
    54  	as := &accountSet{
    55  		accounts: make(map[types.Address]struct{}),
    56  	}
    57  	for _, addr := range addrs {
    58  		as.add(addr)
    59  	}
    60  	return as
    61  }
    62  
    63  // contains checks if a given address is contained within the set.
    64  func (as *accountSet) contains(addr types.Address) bool {
    65  	_, exist := as.accounts[addr]
    66  	return exist
    67  }
    68  
    69  func (as *accountSet) empty() bool {
    70  	return len(as.accounts) == 0
    71  }
    72  
    73  // containsTx checks if the sender of a given tx is within the set. If the sender
    74  // cannot be derived, this method returns false.
    75  func (as *accountSet) containsTx(tx *transaction.Transaction) bool {
    76  	return as.contains(*tx.From())
    77  }
    78  
    79  // add inserts a new address into the set to track.
    80  func (as *accountSet) add(addr types.Address) {
    81  	as.accounts[addr] = struct{}{}
    82  	as.cache = nil
    83  }
    84  
    85  // addTx adds the sender of tx into the set.
    86  func (as *accountSet) addTx(tx *transaction.Transaction) {
    87  	as.add(*tx.From())
    88  }
    89  
    90  // flatten returns the list of addresses within this set, also caching it for later
    91  // reuse. The returned slice should not be changed!
    92  func (as *accountSet) flatten() []types.Address {
    93  	if as.cache == nil {
    94  		accounts := make([]types.Address, 0, len(as.accounts))
    95  		for account := range as.accounts {
    96  			accounts = append(accounts, account)
    97  		}
    98  		as.cache = &accounts
    99  	}
   100  	return *as.cache
   101  }
   102  
   103  // merge adds all addresses from the 'other' set into 'as'.
   104  func (as *accountSet) merge(other *accountSet) {
   105  	for addr := range other.accounts {
   106  		as.accounts[addr] = struct{}{}
   107  	}
   108  	as.cache = nil
   109  }
   110  
   111  // txLookup is used internally by TxPool to track transactions while allowing
   112  // lookup without mutex contention.
   113  //
   114  // Note, although this type is properly protected against concurrent access, it
   115  // is **not** a type that should ever be mutated or even exposed outside of the
   116  // transaction pool, since its internal state is tightly coupled with the pools
   117  // internal mechanisms. The sole purpose of the type is to permit out-of-bound
   118  // peeking into the pool in TxPool.Get without having to acquire the widely scoped
   119  // TxPool.mu mutex.
   120  //
   121  // This lookup set combines the notion of "local transactions", which is useful
   122  // to build upper-level structure.
   123  type txLookup struct {
   124  	slots   int
   125  	lock    sync.RWMutex
   126  	locals  map[types.Hash]*transaction.Transaction
   127  	remotes map[types.Hash]*transaction.Transaction
   128  }
   129  
   130  // newTxLookup returns a new txLookup structure.
   131  func newTxLookup() *txLookup {
   132  	return &txLookup{
   133  		locals:  make(map[types.Hash]*transaction.Transaction),
   134  		remotes: make(map[types.Hash]*transaction.Transaction),
   135  	}
   136  }
   137  
   138  // Range calls f on each key and value present in the map. The callback passed
   139  // should return the indicator whether the iteration needs to be continued.
   140  // Callers need to specify which set (or both) to be iterated.
   141  func (t *txLookup) Range(f func(hash types.Hash, tx *transaction.Transaction, local bool) bool, local bool, remote bool) {
   142  	t.lock.RLock()
   143  	defer t.lock.RUnlock()
   144  
   145  	if local {
   146  		for key, value := range t.locals {
   147  			if !f(key, value, true) {
   148  				return
   149  			}
   150  		}
   151  	}
   152  	if remote {
   153  		for key, value := range t.remotes {
   154  			if !f(key, value, false) {
   155  				return
   156  			}
   157  		}
   158  	}
   159  }
   160  
   161  // Get returns a transaction if it exists in the lookup, or nil if not found.
   162  func (t *txLookup) Get(hash types.Hash) *transaction.Transaction {
   163  	t.lock.RLock()
   164  	defer t.lock.RUnlock()
   165  
   166  	if tx := t.locals[hash]; tx != nil {
   167  		return tx
   168  	}
   169  	return t.remotes[hash]
   170  }
   171  
   172  // GetLocal returns a transaction if it exists in the lookup, or nil if not found.
   173  func (t *txLookup) GetLocal(hash types.Hash) *transaction.Transaction {
   174  	t.lock.RLock()
   175  	defer t.lock.RUnlock()
   176  
   177  	return t.locals[hash]
   178  }
   179  
   180  // GetRemote returns a transaction if it exists in the lookup, or nil if not found.
   181  func (t *txLookup) GetRemote(hash types.Hash) *transaction.Transaction {
   182  	t.lock.RLock()
   183  	defer t.lock.RUnlock()
   184  
   185  	return t.remotes[hash]
   186  }
   187  
   188  // Count returns the current number of transactions in the lookup.
   189  func (t *txLookup) Count() int {
   190  	t.lock.RLock()
   191  	defer t.lock.RUnlock()
   192  
   193  	return len(t.locals) + len(t.remotes)
   194  }
   195  
   196  // LocalCount returns the current number of local transactions in the lookup.
   197  func (t *txLookup) LocalCount() int {
   198  	t.lock.RLock()
   199  	defer t.lock.RUnlock()
   200  
   201  	return len(t.locals)
   202  }
   203  
   204  // RemoteCount returns the current number of remote transactions in the lookup.
   205  func (t *txLookup) RemoteCount() int {
   206  	t.lock.RLock()
   207  	defer t.lock.RUnlock()
   208  
   209  	return len(t.remotes)
   210  }
   211  
   212  // Slots returns the current number of slots used in the lookup.
   213  func (t *txLookup) Slots() int {
   214  	t.lock.RLock()
   215  	defer t.lock.RUnlock()
   216  
   217  	return t.slots
   218  }
   219  
   220  // Add adds a transaction to the lookup.
   221  func (t *txLookup) Add(tx *transaction.Transaction, local bool) {
   222  	t.lock.Lock()
   223  	defer t.lock.Unlock()
   224  
   225  	t.slots += numSlots(tx)
   226  	//todo slotsGauge.Update(int64(t.slots))
   227  
   228  	hash := tx.Hash()
   229  	if local {
   230  		t.locals[hash] = tx
   231  	} else {
   232  		t.remotes[hash] = tx
   233  	}
   234  }
   235  
   236  // Remove removes a transaction from the lookup.
   237  func (t *txLookup) Remove(hash types.Hash) {
   238  	t.lock.Lock()
   239  	defer t.lock.Unlock()
   240  
   241  	tx, ok := t.locals[hash]
   242  	if !ok {
   243  		tx, ok = t.remotes[hash]
   244  	}
   245  	if !ok {
   246  		//todo
   247  		//log.Error("No transaction found to be deleted", "hash", hash)
   248  		return
   249  	}
   250  	t.slots -= numSlots(tx)
   251  	//todo slotsGauge.Update(int64(t.slots))
   252  
   253  	delete(t.locals, hash)
   254  	delete(t.remotes, hash)
   255  }
   256  
   257  // RemoteToLocals migrates the transactions belongs to the given locals to locals
   258  // set. The assumption is held the locals set is thread-safe to be used.
   259  func (t *txLookup) RemoteToLocals(locals *accountSet) int {
   260  	t.lock.Lock()
   261  	defer t.lock.Unlock()
   262  
   263  	var migrated int
   264  	for hash, tx := range t.remotes {
   265  		if locals.containsTx(tx) {
   266  			t.locals[hash] = tx
   267  			delete(t.remotes, hash)
   268  			migrated += 1
   269  		}
   270  	}
   271  	return migrated
   272  }
   273  
   274  // RemotesBelowTip finds all remote transactions below the given tip threshold.
   275  func (t *txLookup) RemotesBelowTip(threshold uint256.Int) []*transaction.Transaction {
   276  	found := make([]*transaction.Transaction, 0, 128)
   277  	t.Range(func(hash types.Hash, tx *transaction.Transaction, local bool) bool {
   278  		if tx.GasPrice().Cmp(&threshold) < 0 {
   279  			found = append(found, tx)
   280  		}
   281  		return true
   282  	}, false, true) // Only iterate remotes
   283  	return found
   284  }
   285  
   286  // numSlots calculates the number of slots needed for a single transaction.
   287  func numSlots(tx *transaction.Transaction) int {
   288  	//todo
   289  	return int((int(unsafe.Sizeof(tx)) + txSlotSize - 1) / txSlotSize)
   290  }
   291  
   292  // TxByNonce implements the sort interface to allow sorting a list of transactions by their nonces.
   293  type TxByNonce []*transaction.Transaction
   294  
   295  func (s TxByNonce) Len() int           { return len(s) }
   296  func (s TxByNonce) Less(i, j int) bool { return s[i].Nonce() < s[j].Nonce() }
   297  func (s TxByNonce) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   298  
   299  // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
   300  // retrieving sorted transactions from the possibly gapped future queue.
   301  type nonceHeap []uint64
   302  
   303  func (h nonceHeap) Len() int           { return len(h) }
   304  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
   305  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
   306  
   307  func (h *nonceHeap) Push(x interface{}) {
   308  	*h = append(*h, x.(uint64))
   309  }
   310  
   311  func (h *nonceHeap) Pop() interface{} {
   312  	old := *h
   313  	n := len(old)
   314  	x := old[n-1]
   315  	*h = old[0 : n-1]
   316  	return x
   317  }
   318  
   319  // txsSortedMap
   320  type txsSortedMap struct {
   321  	items map[uint64]*transaction.Transaction // hash map
   322  	index *nonceHeap                          //
   323  	cache []*transaction.Transaction          // Cache
   324  }
   325  
   326  // newTxSortedMap creates a new nonce-sorted transaction map.
   327  func newTxSortedMap() *txsSortedMap {
   328  	return &txsSortedMap{
   329  		items: make(map[uint64]*transaction.Transaction),
   330  		index: new(nonceHeap),
   331  	}
   332  }
   333  
   334  // Get retrieves the current transactions associated with the given nonce.
   335  func (m *txsSortedMap) Get(nonce uint64) *transaction.Transaction {
   336  	return m.items[nonce]
   337  }
   338  
   339  // Put
   340  func (m *txsSortedMap) Put(tx *transaction.Transaction) {
   341  	nonce := tx.Nonce()
   342  	if m.items[nonce] == nil {
   343  		heap.Push(m.index, nonce)
   344  	}
   345  	m.items[nonce], m.cache = tx, nil
   346  }
   347  
   348  // Forward
   349  func (m *txsSortedMap) Forward(threshold uint64) []*transaction.Transaction {
   350  	var removed []*transaction.Transaction
   351  
   352  	// Pop off heap items until the threshold is reached
   353  	for m.index.Len() > 0 && (*m.index)[0] < threshold {
   354  		nonce := heap.Pop(m.index).(uint64)
   355  		removed = append(removed, m.items[nonce])
   356  		delete(m.items, nonce)
   357  	}
   358  	// If we had a cached order, shift the front
   359  	if m.cache != nil {
   360  		m.cache = m.cache[len(removed):]
   361  	}
   362  	return removed
   363  }
   364  
   365  // Filter
   366  func (m *txsSortedMap) Filter(filter func(*transaction.Transaction) bool) []*transaction.Transaction {
   367  	removed := m.filter(filter)
   368  	// If transactions were removed, the heap and cache are ruined
   369  	if len(removed) > 0 {
   370  		m.reheap()
   371  	}
   372  	return removed
   373  }
   374  
   375  func (m *txsSortedMap) reheap() {
   376  	*m.index = make([]uint64, 0, len(m.items))
   377  	for nonce := range m.items {
   378  		*m.index = append(*m.index, nonce)
   379  	}
   380  	heap.Init(m.index)
   381  	m.cache = nil
   382  }
   383  
   384  // filter is identical to Filter, but **does not** regenerate the heap. This method
   385  // should only be used if followed immediately by a call to Filter or reheap()
   386  func (m *txsSortedMap) filter(filter func(*transaction.Transaction) bool) []*transaction.Transaction {
   387  	var removed []*transaction.Transaction
   388  
   389  	// Collect all the transactions to filter out
   390  	for nonce, tx := range m.items {
   391  		if filter(tx) {
   392  			removed = append(removed, tx)
   393  			delete(m.items, nonce)
   394  		}
   395  	}
   396  	if len(removed) > 0 {
   397  		m.cache = nil
   398  	}
   399  	return removed
   400  }
   401  
   402  // Cap
   403  func (m *txsSortedMap) Cap(threshold int) []*transaction.Transaction {
   404  	// Short circuit if the number of items is under the limit
   405  	if len(m.items) <= threshold {
   406  		return nil
   407  	}
   408  	// Otherwise gather and drop the highest nonce'd transactions
   409  	var drops []*transaction.Transaction
   410  
   411  	sort.Sort(*m.index)
   412  	for size := len(m.items); size > threshold; size-- {
   413  		drops = append(drops, m.items[(*m.index)[size-1]])
   414  		delete(m.items, (*m.index)[size-1])
   415  	}
   416  	*m.index = (*m.index)[:threshold]
   417  	heap.Init(m.index)
   418  
   419  	// If we had a cache, shift the back
   420  	if m.cache != nil {
   421  		m.cache = m.cache[:len(m.cache)-len(drops)]
   422  	}
   423  	return drops
   424  }
   425  
   426  // Remove
   427  func (m *txsSortedMap) Remove(nonce uint64) bool {
   428  	// Short circuit if no transaction is present
   429  	_, ok := m.items[nonce]
   430  	if !ok {
   431  		return false
   432  	}
   433  	// Otherwise delete the transaction and fix the heap index
   434  	for i := 0; i < m.index.Len(); i++ {
   435  		if (*m.index)[i] == nonce {
   436  			heap.Remove(m.index, i)
   437  			break
   438  		}
   439  	}
   440  	delete(m.items, nonce)
   441  	m.cache = nil
   442  
   443  	return true
   444  }
   445  
   446  // Ready retrieves a sequentially increasing list of transactions starting at the
   447  // provided nonce that is ready for processing. The returned transactions will be
   448  // removed from the list.
   449  //
   450  // Note, all transactions with nonces lower than start will also be returned to
   451  // prevent getting into and invalid state. This is not something that should ever
   452  // happen but better to be self correcting than failing!
   453  func (m *txsSortedMap) Ready(start uint64) []*transaction.Transaction {
   454  	// Short circuit if no transactions are available
   455  	if m.index.Len() == 0 || (*m.index)[0] > start {
   456  		return nil
   457  	}
   458  	// Otherwise start accumulating incremental transactions
   459  	var ready []*transaction.Transaction
   460  	for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   461  		ready = append(ready, m.items[next])
   462  		delete(m.items, next)
   463  		heap.Pop(m.index)
   464  	}
   465  	m.cache = nil
   466  
   467  	return ready
   468  }
   469  
   470  // Len returns the length of the transaction map.
   471  func (m *txsSortedMap) Len() int {
   472  	return len(m.items)
   473  }
   474  
   475  func (m *txsSortedMap) flatten() []*transaction.Transaction {
   476  	// If the sorting was not cached yet, create and cache it
   477  	if m.cache == nil {
   478  		m.cache = make([]*transaction.Transaction, 0, len(m.items))
   479  		for _, tx := range m.items {
   480  			m.cache = append(m.cache, tx)
   481  		}
   482  		sort.Sort(TxByNonce(m.cache))
   483  	}
   484  	return m.cache
   485  }
   486  
   487  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   488  // sorted internal representation. The result of the sorting is cached in case
   489  // it's requested again before any modifications are made to the contents.
   490  func (m *txsSortedMap) Flatten() []*transaction.Transaction {
   491  	// Copy the cache to prevent accidental modifications
   492  	cache := m.flatten()
   493  	txs := make([]*transaction.Transaction, len(cache))
   494  	copy(txs, cache)
   495  	return txs
   496  }
   497  
   498  // LastElement returns the last element of a flattened list, thus, the
   499  // transaction with the highest nonce
   500  func (m *txsSortedMap) LastElement() *transaction.Transaction {
   501  	cache := m.flatten()
   502  	return cache[len(cache)-1]
   503  }
   504  
   505  // txsList is a "list" of transactions belonging to an account, sorted by account
   506  // nonce. The same type can be used both for storing contiguous transactions for
   507  // the executable/pending queue; and for storing gapped transactions for the non-
   508  // executable/future queue, with minor behavioral changes.
   509  type txsList struct {
   510  	strict  bool
   511  	txs     *txsSortedMap
   512  	costcap uint256.Int
   513  	gascap  uint64
   514  }
   515  
   516  // newtxsList create a new transaction list for maintaining nonce-indexable fast,
   517  // gapped, sortable transaction lists.
   518  func newTxsList(strict bool) *txsList {
   519  	return &txsList{
   520  		strict:  strict,
   521  		txs:     newTxSortedMap(),
   522  		costcap: *uint256.NewInt(0),
   523  	}
   524  }
   525  
   526  // Overlaps returns whether the transaction specified has the same nonce as one
   527  // already contained within the list.
   528  func (l *txsList) Overlaps(tx *transaction.Transaction) bool {
   529  	return l.txs.Get(tx.Nonce()) != nil
   530  }
   531  
   532  // Add tries to insert a new transaction into the list, returning whether the
   533  // transaction was accepted, and if yes, any previous transaction it replaced.
   534  //
   535  // If the new transaction is accepted into the list, the lists' cost and gas
   536  // thresholds are also potentially updated.
   537  func (l *txsList) Add(tx *transaction.Transaction, priceBump uint64) (bool, *transaction.Transaction) {
   538  	// If there's an older better transaction, abort
   539  
   540  	old := l.txs.Get(tx.Nonce())
   541  	if old != nil {
   542  		if old.GasFeeCapCmp(tx) >= 1 || old.GasTipCapCmp(tx) >= 1 {
   543  			return false, nil
   544  		}
   545  		// thresholdFeeCap = oldFC  * (100 + priceBump) / 100
   546  		a := uint256.NewInt(100 + priceBump)
   547  		aFeeCap := new(uint256.Int).Mul(a, old.GasFeeCap())
   548  		aTip := a.Mul(a, old.GasTipCap())
   549  
   550  		// thresholdTip    = oldTip * (100 + priceBump) / 100
   551  		b := uint256.NewInt(100)
   552  		thresholdFeeCap := aFeeCap.Div(aFeeCap, b)
   553  		thresholdTip := aTip.Div(aTip, b)
   554  
   555  		// We have to ensure that both the new fee cap and tip are higher than the
   556  		// old ones as well as checking the percentage threshold to ensure that
   557  		// this is accurate for low (Wei-level) gas price replacements.
   558  		if tx.GasFeeCapIntCmp(thresholdFeeCap) < 0 || tx.GasTipCapIntCmp(thresholdTip) < 0 {
   559  			return false, nil
   560  		}
   561  	}
   562  	// Otherwise overwrite the old transaction with the current one
   563  	l.txs.Put(tx)
   564  
   565  	cost := uint256.NewInt(0).Add(new(uint256.Int).Mul(tx.GasPrice(), uint256.NewInt(tx.Gas())), tx.Value())
   566  
   567  	if l.costcap.Cmp(cost) < 0 {
   568  		l.costcap = *cost
   569  	}
   570  	if gas := tx.Gas(); l.gascap < gas {
   571  		l.gascap = gas
   572  	}
   573  	return true, old
   574  }
   575  
   576  // Forward removes all transactions from the list with a nonce lower than the
   577  // provided threshold. Every removed transaction is returned for any post-removal
   578  // maintenance.
   579  func (l *txsList) Forward(threshold uint64) []*transaction.Transaction {
   580  	return l.txs.Forward(threshold)
   581  }
   582  
   583  // Filter removes all transactions from the list with a cost or gas limit higher
   584  // than the provided thresholds. Every removed transaction is returned for any
   585  // post-removal maintenance. Strict-mode invalidated transactions are also
   586  // returned.
   587  //
   588  // This method uses the cached costcap and gascap to quickly decide if there's even
   589  // a point in calculating all the costs or if the balance covers all. If the threshold
   590  // is lower than the costgas cap, the caps will be reset to a new high after removing
   591  // the newly invalidated transactions.
   592  func (l *txsList) Filter(costLimit uint256.Int, gasLimit uint64) ([]*transaction.Transaction, []*transaction.Transaction) {
   593  	// If all transactions are below the threshold, short circuit
   594  	if l.costcap.Cmp(&costLimit) <= 0 && l.gascap <= gasLimit {
   595  		return nil, nil
   596  	}
   597  	l.costcap = costLimit // Lower the caps to the thresholds
   598  	l.gascap = gasLimit
   599  
   600  	// Filter out all the transactions above the account's funds
   601  	removed := l.txs.Filter(func(tx *transaction.Transaction) bool {
   602  		cost := uint256.NewInt(0).Add(tx.Value(), uint256.NewInt(0).Mul(tx.GasPrice(), uint256.NewInt(tx.Gas())))
   603  		return tx.Gas() > gasLimit || cost.Cmp(&costLimit) > 0
   604  	})
   605  
   606  	if len(removed) == 0 {
   607  		return nil, nil
   608  	}
   609  	var invalids []*transaction.Transaction
   610  	// If the list was strict, filter anything above the lowest nonce
   611  	if l.strict {
   612  		lowest := uint64(math.MaxUint64)
   613  		for _, tx := range removed {
   614  			if nonce := tx.Nonce(); lowest > nonce {
   615  				lowest = nonce
   616  			}
   617  		}
   618  		invalids = l.txs.filter(func(tx *transaction.Transaction) bool { return tx.Nonce() > lowest })
   619  	}
   620  	l.txs.reheap()
   621  	return removed, invalids
   622  }
   623  
   624  // Cap places a hard limit on the number of items, returning all transactions
   625  // exceeding that limit.
   626  func (l *txsList) Cap(threshold int) []*transaction.Transaction {
   627  	return l.txs.Cap(threshold)
   628  }
   629  
   630  // Remove deletes a transaction from the maintained list, returning whether the
   631  // transaction was found, and also returning any transaction invalidated due to
   632  // the deletion (strict mode only).
   633  func (l *txsList) Remove(tx *transaction.Transaction) (bool, []*transaction.Transaction) {
   634  	// Remove the transaction from the set
   635  	nonce := tx.Nonce()
   636  	if removed := l.txs.Remove(nonce); !removed {
   637  		return false, nil
   638  	}
   639  	// In strict mode, filter out non-executable transactions
   640  	if l.strict {
   641  		return true, l.txs.Filter(func(tx *transaction.Transaction) bool { return tx.Nonce() > nonce })
   642  	}
   643  	return true, nil
   644  }
   645  
   646  // Ready retrieves a sequentially increasing list of transactions starting at the
   647  // provided nonce that is ready for processing. The returned transactions will be
   648  // removed from the list.
   649  //
   650  // Note, all transactions with nonces lower than start will also be returned to
   651  // prevent getting into and invalid state. This is not something that should ever
   652  // happen but better to be self correcting than failing!
   653  func (l *txsList) Ready(start uint64) []*transaction.Transaction {
   654  	return l.txs.Ready(start)
   655  }
   656  
   657  // Len returns the length of the transaction list.
   658  func (l *txsList) Len() int {
   659  	return l.txs.Len()
   660  }
   661  
   662  // Empty returns whether the list of transactions is empty or not.
   663  func (l *txsList) Empty() bool {
   664  	return l.Len() == 0
   665  }
   666  
   667  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   668  // sorted internal representation. The result of the sorting is cached in case
   669  // it's requested again before any modifications are made to the contents.
   670  func (l *txsList) Flatten() []*transaction.Transaction {
   671  	return l.txs.Flatten()
   672  }
   673  
   674  // LastElement returns the last element of a flattened list, thus, the
   675  // transaction with the highest nonce
   676  func (l *txsList) LastElement() *transaction.Transaction {
   677  	return l.txs.LastElement()
   678  }
   679  
   680  // priceHeap is a heap.Interface implementation over transactions for retrieving
   681  // price-sorted transactions to discard when the pool fills up. If baseFee is set
   682  // then the heap is sorted based on the effective tip based on the given base fee.
   683  // If baseFee is nil then the sorting is based on gasFeeCap.
   684  type priceHeap struct {
   685  	baseFee *uint256.Int // heap should always be re-sorted after baseFee is changed
   686  	list    []*transaction.Transaction
   687  }
   688  
   689  func (h *priceHeap) Len() int      { return len(h.list) }
   690  func (h *priceHeap) Swap(i, j int) { h.list[i], h.list[j] = h.list[j], h.list[i] }
   691  
   692  func (h *priceHeap) Less(i, j int) bool {
   693  	switch h.cmp(h.list[i], h.list[j]) {
   694  	case -1:
   695  		return true
   696  	case 1:
   697  		return false
   698  	default:
   699  		return h.list[i].Nonce() > h.list[j].Nonce()
   700  	}
   701  }
   702  
   703  func (h *priceHeap) cmp(a, b *transaction.Transaction) int {
   704  	if h.baseFee != nil {
   705  		// Compare effective tips if baseFee is specified
   706  		if c := a.EffectiveGasTipCmp(b, h.baseFee); c != 0 {
   707  			return c
   708  		}
   709  	}
   710  	// Compare fee caps if baseFee is not specified or effective tips are equal
   711  	if c := a.GasPrice().Cmp(b.GasPrice()); c != 0 {
   712  		return c
   713  	}
   714  	// Compare tips if effective tips and fee caps are equal
   715  	return a.GasPrice().Cmp(b.GasPrice())
   716  }
   717  
   718  func (h *priceHeap) Push(x interface{}) {
   719  	tx := x.(*transaction.Transaction)
   720  	h.list = append(h.list, tx)
   721  }
   722  
   723  func (h *priceHeap) Pop() interface{} {
   724  	old := h.list
   725  	n := len(old)
   726  	x := old[n-1]
   727  	old[n-1] = nil
   728  	h.list = old[0 : n-1]
   729  	return x
   730  }
   731  
   732  // txPricedList is a price-sorted heap to allow operating on transactions pool
   733  // contents in a price-incrementing way. It's built opon the all transactions
   734  // in txpool but only interested in the remote part. It means only remote transactions
   735  // will be considered for tracking, sorting, eviction, etc.
   736  //
   737  // Two heaps are used for sorting: the urgent heap (based on effective tip in the next
   738  // block) and the floating heap (based on gasFeeCap). Always the bigger heap is chosen for
   739  // eviction. Transactions evicted from the urgent heap are first demoted into the floating heap.
   740  // In some cases (during a congestion, when blocks are full) the urgent heap can provide
   741  // better candidates for inclusion while in other cases (at the top of the baseFee peak)
   742  // the floating heap is better. When baseFee is decreasing they behave similarly.
   743  type txPricedList struct {
   744  	// Number of stale price points to (re-heap trigger).
   745  	// This field is accessed atomically, and must be the first field
   746  	// to ensure it has correct alignment for atomic.AddInt64.
   747  	// See https://golang.org/pkg/sync/atomic/#pkg-note-BUG.
   748  	stales int64
   749  
   750  	all              *txLookup  // Pointer to the map of all transactions
   751  	urgent, floating priceHeap  // Heaps of prices of all the stored **remote** transactions
   752  	reheapMu         sync.Mutex // Mutex asserts that only one routine is reheaping the list
   753  }
   754  
   755  const (
   756  	// urgentRatio : floatingRatio is the capacity ratio of the two queues
   757  	urgentRatio   = 4
   758  	floatingRatio = 1
   759  )
   760  
   761  // newTxPricedList creates a new price-sorted transaction heap.
   762  func newTxPricedList(all *txLookup) *txPricedList {
   763  	return &txPricedList{
   764  		all: all,
   765  	}
   766  }
   767  
   768  // Put inserts a new transaction into the heap.
   769  func (l *txPricedList) Put(tx *transaction.Transaction, local bool) {
   770  	if local {
   771  		return
   772  	}
   773  	// Insert every new transaction to the urgent heap first; Discard will balance the heaps
   774  	heap.Push(&l.urgent, tx)
   775  }
   776  
   777  // Removed notifies the prices transaction list that an old transaction dropped
   778  // from the pool. The list will just keep a counter of stale objects and update
   779  // the heap if a large enough ratio of transactions go stale.
   780  func (l *txPricedList) Removed(count int) {
   781  	// Bump the stale counter, but exit if still too low (< 25%)
   782  	stales := atomic.AddInt64(&l.stales, int64(count))
   783  	if int(stales) <= (len(l.urgent.list)+len(l.floating.list))/4 {
   784  		return
   785  	}
   786  	// Seems we've reached a critical number of stale transactions, reheap
   787  	l.Reheap()
   788  }
   789  
   790  // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
   791  // lowest priced (remote) transaction currently being tracked.
   792  func (l *txPricedList) Underpriced(tx *transaction.Transaction) bool {
   793  	// Note: with two queues, being underpriced is defined as being worse than the worst item
   794  	// in all non-empty queues if there is any. If both queues are empty then nothing is underpriced.
   795  	return (l.underpricedFor(&l.urgent, tx) || len(l.urgent.list) == 0) &&
   796  		(l.underpricedFor(&l.floating, tx) || len(l.floating.list) == 0) &&
   797  		(len(l.urgent.list) != 0 || len(l.floating.list) != 0)
   798  }
   799  
   800  // underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
   801  // lowest priced (remote) transaction in the given heap.
   802  func (l *txPricedList) underpricedFor(h *priceHeap, tx *transaction.Transaction) bool {
   803  	// Discard stale price points if found at the heap start
   804  	for len(h.list) > 0 {
   805  		hash := h.list[0].Hash()
   806  		if l.all.GetRemote(hash) == nil { // Removed or migrated
   807  			atomic.AddInt64(&l.stales, -1)
   808  			heap.Pop(h)
   809  			continue
   810  		}
   811  		break
   812  	}
   813  	// Check if the transaction is underpriced or not
   814  	if len(h.list) == 0 {
   815  		return false // There is no remote transaction at all.
   816  	}
   817  	// If the remote transaction is even cheaper than the
   818  	// cheapest one tracked locally, reject it.
   819  	return h.cmp(h.list[0], tx) >= 0
   820  }
   821  
   822  // Discard finds a number of most underpriced transactions, removes them from the
   823  // priced list and returns them for further removal from the entire pool.
   824  //
   825  // Note local transaction won't be considered for eviction.
   826  func (l *txPricedList) Discard(slots int, force bool) ([]*transaction.Transaction, bool) {
   827  	drop := make([]*transaction.Transaction, 0, slots) // Remote underpriced transactions to drop
   828  	for slots > 0 {
   829  		if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio || floatingRatio == 0 {
   830  			// Discard stale transactions if found during cleanup
   831  			tx := heap.Pop(&l.urgent).(*transaction.Transaction)
   832  			hash := tx.Hash()
   833  			if l.all.GetRemote(hash) == nil { // Removed or migrated
   834  				atomic.AddInt64(&l.stales, -1)
   835  				continue
   836  			}
   837  			// Non stale transaction found, move to floating heap
   838  			heap.Push(&l.floating, tx)
   839  		} else {
   840  			if len(l.floating.list) == 0 {
   841  				// Stop if both heaps are empty
   842  				break
   843  			}
   844  			// Discard stale transactions if found during cleanup
   845  			tx := heap.Pop(&l.floating).(*transaction.Transaction)
   846  			hash := tx.Hash()
   847  			if l.all.GetRemote(hash) == nil { // Removed or migrated
   848  				atomic.AddInt64(&l.stales, -1)
   849  				continue
   850  			}
   851  			// Non stale transaction found, discard it
   852  			drop = append(drop, tx)
   853  			slots -= numSlots(tx)
   854  		}
   855  	}
   856  	// If we still can't make enough room for the new transaction
   857  	if slots > 0 && !force {
   858  		for _, tx := range drop {
   859  			heap.Push(&l.urgent, tx)
   860  		}
   861  		return nil, false
   862  	}
   863  	return drop, true
   864  }
   865  
   866  // Reheap forcibly rebuilds the heap based on the current remote transaction set.
   867  func (l *txPricedList) Reheap() {
   868  	l.reheapMu.Lock()
   869  	defer l.reheapMu.Unlock()
   870  	//start := time.Now()
   871  	atomic.StoreInt64(&l.stales, 0)
   872  	l.urgent.list = make([]*transaction.Transaction, 0, l.all.RemoteCount())
   873  	l.all.Range(func(hash types.Hash, tx *transaction.Transaction, local bool) bool {
   874  		l.urgent.list = append(l.urgent.list, tx)
   875  		return true
   876  	}, false, true) // Only iterate remotes
   877  	heap.Init(&l.urgent)
   878  
   879  	// balance out the two heaps by moving the worse half of transactions into the
   880  	// floating heap
   881  	// Note: Discard would also do this before the first eviction but Reheap can do
   882  	// is more efficiently. Also, Underpriced would work suboptimally the first time
   883  	// if the floating queue was empty.
   884  	floatingCount := len(l.urgent.list) * floatingRatio / (urgentRatio + floatingRatio)
   885  	l.floating.list = make([]*transaction.Transaction, floatingCount)
   886  	for i := 0; i < floatingCount; i++ {
   887  		l.floating.list[i] = heap.Pop(&l.urgent).(*transaction.Transaction)
   888  	}
   889  	heap.Init(&l.floating)
   890  
   891  	//todo reheapTimer.Update(time.Since(start))
   892  }
   893  
   894  // SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
   895  // necessary to call right before SetBaseFee when processing a new block.
   896  func (l *txPricedList) SetBaseFee(baseFee *uint256.Int) {
   897  	l.urgent.baseFee = baseFee
   898  	l.Reheap()
   899  }