github.com/gochain-io/gochain@v2.2.26+incompatible/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/big"
    22  	"sort"
    23  
    24  	"github.com/gochain-io/gochain/core/types"
    25  )
    26  
    27  // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
    28  // retrieving sorted transactions from the possibly gapped future queue.
    29  type nonceHeap []uint64
    30  
    31  func (h nonceHeap) Len() int           { return len(h) }
    32  func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
    33  func (h nonceHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
    34  
    35  func (h *nonceHeap) Push(x interface{}) {
    36  	*h = append(*h, x.(uint64))
    37  }
    38  
    39  func (h *nonceHeap) Pop() interface{} {
    40  	old := *h
    41  	n := len(old)
    42  	x := old[n-1]
    43  	*h = old[0 : n-1]
    44  	return x
    45  }
    46  
    47  // txSortedMap is a nonce->transaction hash map with a heap based index to allow
    48  // iterating over the contents in a nonce-incrementing way.
    49  type txSortedMap struct {
    50  	items map[uint64]*types.Transaction // Hash map storing the transaction data
    51  	index *nonceHeap                    // Heap of nonces of all the stored transactions (non-strict mode)
    52  	cache types.Transactions            // Cache of the transactions already sorted
    53  }
    54  
    55  // newTxSortedMap creates a new nonce-sorted transaction map.
    56  func newTxSortedMap() *txSortedMap {
    57  	return &txSortedMap{
    58  		items: make(map[uint64]*types.Transaction),
    59  		index: &nonceHeap{},
    60  	}
    61  }
    62  
    63  // Get retrieves the current transactions associated with the given nonce.
    64  func (m *txSortedMap) Get(nonce uint64) *types.Transaction {
    65  	return m.items[nonce]
    66  }
    67  
    68  // Put inserts a new transaction into the map, also updating the map's nonce
    69  // index. If a transaction already exists with the same nonce, it's overwritten.
    70  func (m *txSortedMap) Put(tx *types.Transaction) {
    71  	nonce := tx.Nonce()
    72  	if m.items[nonce] == nil {
    73  		heap.Push(m.index, nonce)
    74  	}
    75  	m.items[nonce], m.cache = tx, nil
    76  }
    77  
    78  // Forward removes all transactions from the map with a nonce lower than the
    79  // provided threshold. Every removed transaction is passed to fn for any post-removal
    80  // maintenance.
    81  func (m *txSortedMap) Forward(threshold uint64, fn func(*types.Transaction)) {
    82  	var removed int
    83  	// Pop off heap items until the threshold is reached
    84  	for m.index.Len() > 0 && (*m.index)[0] < threshold {
    85  		nonce := heap.Pop(m.index).(uint64)
    86  		item := m.items[nonce]
    87  		delete(m.items, nonce)
    88  		fn(item)
    89  		removed++
    90  	}
    91  	// If we had a cached order, shift the front
    92  	if m.cache != nil {
    93  		m.cache = m.cache[removed:]
    94  	}
    95  }
    96  
    97  // Filter iterates over the list of transactions calling filter, removing and calling removed for each match. If strict
    98  // is true, then all txs with nonces higher than the first match are removed and passed to invalid.
    99  func (m *txSortedMap) Filter(filter func(*types.Transaction) bool, strict bool, removed, invalid func(*types.Transaction)) {
   100  	if strict {
   101  		// Iterate in order so we can slice off the higher nonces.
   102  		m.ensureCache()
   103  		for i, tx := range m.cache {
   104  			if !filter(tx) {
   105  				continue
   106  			}
   107  			delete(m.items, tx.Nonce())
   108  			removed(tx)
   109  
   110  			if len(m.cache) > i+1 {
   111  				for _, tx := range m.cache[i+1:] {
   112  					delete(m.items, tx.Nonce())
   113  					invalid(tx)
   114  				}
   115  			}
   116  
   117  			m.cache = m.cache[:i]
   118  
   119  			// Rebuild heap.
   120  			*m.index = make([]uint64, 0, len(m.items))
   121  			for nonce := range m.items {
   122  				*m.index = append(*m.index, nonce)
   123  			}
   124  			heap.Init(m.index)
   125  
   126  			return
   127  		}
   128  		return
   129  	}
   130  
   131  	var matched bool
   132  	for nonce, tx := range m.items {
   133  		if !filter(tx) {
   134  			continue
   135  		}
   136  		matched = true
   137  		delete(m.items, nonce)
   138  		removed(tx)
   139  	}
   140  
   141  	// If transactions were removed, the heap and cache are ruined
   142  	if matched {
   143  		*m.index = make([]uint64, 0, len(m.items))
   144  		for nonce := range m.items {
   145  			*m.index = append(*m.index, nonce)
   146  		}
   147  		heap.Init(m.index)
   148  
   149  		m.cache = nil
   150  	}
   151  }
   152  
   153  // Cap places a hard limit on the number of items, removing and calling removed with each transaction
   154  // exceeding that limit.
   155  func (m *txSortedMap) Cap(threshold int, removed func(*types.Transaction)) {
   156  	// Short circuit if the number of items is under the limit.
   157  	if len(m.items) <= threshold {
   158  		return
   159  	}
   160  
   161  	// Resort the heap to drop the highest nonce'd transactions.
   162  	var drops int
   163  	sort.Sort(*m.index)
   164  	for size := len(m.items); size > threshold; size-- {
   165  		item := m.items[(*m.index)[size-1]]
   166  		delete(m.items, (*m.index)[size-1])
   167  		removed(item)
   168  		drops++
   169  	}
   170  	*m.index = (*m.index)[:threshold]
   171  	// Restore the heap.
   172  	heap.Init(m.index)
   173  
   174  	// If we had a cache, shift the back
   175  	if m.cache != nil {
   176  		m.cache = m.cache[:len(m.cache)-drops]
   177  	}
   178  }
   179  
   180  // Remove deletes a transaction from the maintained map, returning whether the transaction was found. If strict is true
   181  // then it will also remove invalidated txs (higher than nonce) and call invalid for each one.
   182  func (m *txSortedMap) Remove(nonce uint64, strict bool, invalid func(*types.Transaction)) bool {
   183  	// Short circuit if no transaction is present
   184  	_, ok := m.items[nonce]
   185  	if !ok {
   186  		return false
   187  	}
   188  	m.ensureCache()
   189  	delete(m.items, nonce)
   190  	i := sort.Search(len(m.cache), func(i int) bool {
   191  		return m.cache[i].Nonce() >= nonce
   192  	})
   193  
   194  	if !strict {
   195  		// Repair the cache and heap.
   196  		copy(m.cache[i:], m.cache[i+1:])
   197  		m.cache = m.cache[:len(m.cache)-1]
   198  		for i := 0; i < m.index.Len(); i++ {
   199  			if (*m.index)[i] == nonce {
   200  				heap.Remove(m.index, i)
   201  				break
   202  			}
   203  		}
   204  		return true
   205  	}
   206  
   207  	// Remove invalidated.
   208  	for _, tx := range m.cache[i+1:] {
   209  		delete(m.items, tx.Nonce())
   210  		invalid(tx)
   211  	}
   212  
   213  	// Repair the cache and heap.
   214  	m.cache = m.cache[:i]
   215  	*m.index = make([]uint64, 0, len(m.items))
   216  	for nonce := range m.items {
   217  		*m.index = append(*m.index, nonce)
   218  	}
   219  	heap.Init(m.index)
   220  
   221  	return true
   222  }
   223  
   224  // Ready iterates over a sequentially increasing list of transactions that are ready for processing, removing
   225  // and calling fn for each one.
   226  //
   227  // Note, all transactions with nonces lower than start will also be included to
   228  // prevent getting into and invalid state. This is not something that should ever
   229  // happen but better to be self correcting than failing!
   230  func (m *txSortedMap) Ready(start uint64, fn func(*types.Transaction)) {
   231  	// Short circuit if no transactions are available
   232  	if m.index.Len() == 0 || (*m.index)[0] > start {
   233  		return
   234  	}
   235  	if m.cache == nil {
   236  		for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
   237  			heap.Pop(m.index)
   238  			item := m.items[next]
   239  			delete(m.items, next)
   240  			fn(item)
   241  		}
   242  		return
   243  	}
   244  	next := m.cache[0].Nonce()
   245  	for i, item := range m.cache {
   246  		nonce := item.Nonce()
   247  		if nonce != next {
   248  			// Update cache.
   249  			m.cache = m.cache[i:]
   250  			break
   251  		}
   252  		delete(m.items, nonce)
   253  		fn(item)
   254  		next++
   255  	}
   256  	// Rebuild heap.
   257  	*m.index = make([]uint64, 0, len(m.items))
   258  	for nonce := range m.items {
   259  		*m.index = append(*m.index, nonce)
   260  	}
   261  	heap.Init(m.index)
   262  }
   263  
   264  // Len returns the length of the transaction map.
   265  func (m *txSortedMap) Len() int {
   266  	return len(m.items)
   267  }
   268  
   269  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   270  // sorted internal representation. The result of the sorting is cached in case
   271  // it's requested again before any modifications are made to the contents.
   272  func (m *txSortedMap) Flatten() types.Transactions {
   273  	m.ensureCache()
   274  	// Copy the cache to prevent accidental modifications
   275  	txs := make(types.Transactions, len(m.cache))
   276  	copy(txs, m.cache)
   277  	return txs
   278  }
   279  
   280  // ForLast calls fn with each of the last n txs in nonce order. The result of the sorting is cached in case
   281  // it's requested again before any modifications are made to the contents.
   282  func (m *txSortedMap) ForLast(n int, fn func(*types.Transaction)) {
   283  	m.ensureCache()
   284  	i := len(m.cache) - n
   285  	if i < 0 {
   286  		i = 0
   287  	}
   288  	for _, tx := range m.cache[i:] {
   289  		delete(m.items, tx.Nonce())
   290  		fn(tx)
   291  	}
   292  	m.cache = m.cache[:i]
   293  
   294  	// Rebuild heap.
   295  	*m.index = make([]uint64, 0, len(m.items))
   296  	for nonce := range m.items {
   297  		*m.index = append(*m.index, nonce)
   298  	}
   299  	heap.Init(m.index)
   300  }
   301  
   302  // Last returns the highest nonce tx. The result of the sorting is cached in case
   303  // it's requested again before any modifications are made to the contents.
   304  func (m *txSortedMap) Last() *types.Transaction {
   305  	m.ensureCache()
   306  	return m.cache[len(m.cache)-1]
   307  }
   308  
   309  func (m *txSortedMap) ensureCache() {
   310  	// If the sorting was not cached yet, create and cache it
   311  	if m.cache == nil {
   312  		m.cache = make(types.Transactions, 0, len(m.items))
   313  		for _, tx := range m.items {
   314  			m.cache = append(m.cache, tx)
   315  		}
   316  		sort.Sort(types.TxByNonce(m.cache))
   317  	}
   318  }
   319  
   320  // txList is a "list" of transactions belonging to an account, sorted by account
   321  // nonce. The same type can be used both for storing contiguous transactions for
   322  // the executable/pending queue; and for storing gapped transactions for the non-
   323  // executable/future queue, with minor behavioral changes.
   324  type txList struct {
   325  	strict bool         // Whether nonces are strictly continuous or not
   326  	txs    *txSortedMap // Heap indexed sorted hash map of the transactions
   327  
   328  	costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
   329  	gascap  uint64   // Gas limit of the highest spending transaction (reset only if exceeds block limit)
   330  }
   331  
   332  // newTxList create a new transaction list for maintaining nonce-indexable fast,
   333  // gapped, sortable transaction lists.
   334  func newTxList(strict bool) *txList {
   335  	return &txList{
   336  		strict:  strict,
   337  		txs:     newTxSortedMap(),
   338  		costcap: new(big.Int),
   339  	}
   340  }
   341  
   342  // Overlaps returns whether the transaction specified has the same nonce as one
   343  // already contained within the list.
   344  func (l *txList) Overlaps(tx *types.Transaction) bool {
   345  	return l.txs.Get(tx.Nonce()) != nil
   346  }
   347  
   348  // Add tries to insert a new transaction into the list, returning whether the
   349  // transaction was accepted, and if yes, any previous transaction it replaced.
   350  //
   351  // If the new transaction is accepted into the list, the lists' cost and gas
   352  // thresholds are also potentially updated.
   353  func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
   354  	// If there's an older better transaction, abort
   355  	old := l.txs.Get(tx.Nonce())
   356  	if old != nil {
   357  		threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
   358  		// Have to ensure that the new gas price is higher than the old gas
   359  		// price as well as checking the percentage threshold to ensure that
   360  		// this is accurate for low (Wei-level) gas price replacements
   361  		if old.CmpGasPriceTx(tx) >= 0 || tx.CmpGasPrice(threshold) < 0 {
   362  			return false, nil
   363  		}
   364  	}
   365  	// Otherwise overwrite the old transaction with the current one
   366  	l.add(tx)
   367  	return true, old
   368  }
   369  
   370  func (l *txList) add(tx *types.Transaction) {
   371  	l.txs.Put(tx)
   372  	if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
   373  		l.costcap = cost
   374  	}
   375  	if gas := tx.Gas(); l.gascap < gas {
   376  		l.gascap = gas
   377  	}
   378  }
   379  
   380  // Forward removes all transactions from the list with a nonce lower than the
   381  // provided threshold. Every removed transaction is passed to fn for any post-removal
   382  // maintenance.
   383  func (l *txList) Forward(threshold uint64, fn func(*types.Transaction)) {
   384  	l.txs.Forward(threshold, fn)
   385  }
   386  
   387  // Filter removes all transactions from the list with a cost or gas limit higher
   388  // than the provided thresholds. Every removed transaction is returned for any
   389  // post-removal maintenance. Strict-mode invalidated transactions are also
   390  // returned.
   391  //
   392  // This method uses the cached costcap and gascap to quickly decide if there's even
   393  // a point in calculating all the costs or if the balance covers all. If the threshold
   394  // is lower than the costgas cap, the caps will be reset to a new high after removing
   395  // the newly invalidated transactions.
   396  func (l *txList) Filter(costLimit *big.Int, gasLimit uint64, removed, invalid func(*types.Transaction)) {
   397  	// If all transactions are below the threshold, short circuit
   398  	if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
   399  		return
   400  	}
   401  	l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
   402  	l.gascap = gasLimit
   403  
   404  	filter := func(tx *types.Transaction) bool {
   405  		return tx.Cost().Cmp(costLimit) > 0 || tx.Gas() > gasLimit
   406  	}
   407  	l.txs.Filter(filter, l.strict, removed, invalid)
   408  }
   409  
   410  // Cap places a hard limit on the number of items, removing and calling removed with each transaction
   411  // exceeding that limit.
   412  func (l *txList) Cap(threshold int, removed func(*types.Transaction)) {
   413  	l.txs.Cap(threshold, removed)
   414  }
   415  
   416  // Remove deletes a transaction from the maintained list, returning whether the
   417  // transaction was found, and also calling invalid with each transaction invalidated due to
   418  // the deletion (strict mode only).
   419  func (l *txList) Remove(tx *types.Transaction, invalid func(*types.Transaction)) bool {
   420  	return l.txs.Remove(tx.Nonce(), l.strict, invalid)
   421  }
   422  
   423  // Ready iterates over a sequentially increasing list of transactions that are ready for processing, removing
   424  // and calling fn for each one.
   425  //
   426  // Note, all transactions with nonces lower than start will also be included to
   427  // prevent getting into an invalid state. This is not something that should ever
   428  // happen but better to be self correcting than failing!
   429  func (l *txList) Ready(start uint64, fn func(*types.Transaction)) {
   430  	l.txs.Ready(start, fn)
   431  }
   432  
   433  // Len returns the length of the transaction list.
   434  func (l *txList) Len() int {
   435  	return l.txs.Len()
   436  }
   437  
   438  // Empty returns whether the list of transactions is empty or not.
   439  func (l *txList) Empty() bool {
   440  	return l.Len() == 0
   441  }
   442  
   443  // Flatten creates a nonce-sorted slice of transactions based on the loosely
   444  // sorted internal representation. The result of the sorting is cached in case
   445  // it's requested again before any modifications are made to the contents.
   446  func (l *txList) Flatten() types.Transactions {
   447  	return l.txs.Flatten()
   448  }
   449  
   450  // ForLast calls fn with each of the last n txs in nonce order. The result of the sorting is cached in case
   451  // it's requested again before any modifications are made to the contents.
   452  func (l *txList) ForLast(n int, fn func(*types.Transaction)) {
   453  	l.txs.ForLast(n, fn)
   454  }
   455  
   456  // Last returns the highest nonce tx. The result of the sorting is cached in case
   457  // it's requested again before any modifications are made to the contents.
   458  func (l *txList) Last() *types.Transaction {
   459  	return l.txs.Last()
   460  }