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