@@ -20,6 +20,7 @@ import (
2020	"container/heap" 
2121	"math" 
2222	"math/big" 
23+ 	"slices" 
2324	"sort" 
2425	"sync" 
2526	"sync/atomic" 
@@ -49,16 +50,18 @@ func (h *nonceHeap) Pop() interface{} {
4950	old  :=  * h 
5051	n  :=  len (old )
5152	x  :=  old [n - 1 ]
53+ 	old [n - 1 ] =  0 
5254	* h  =  old [0  : n - 1 ]
5355	return  x 
5456}
5557
5658// txSortedMap is a nonce->transaction hash map with a heap based index to allow 
5759// iterating over the contents in a nonce-incrementing way. 
5860type  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 
61+ 	items    map [uint64 ]* types.Transaction  // Hash map storing the transaction data 
62+ 	index    * nonceHeap                     // Heap of nonces of all the stored transactions (non-strict mode) 
63+ 	cache    types.Transactions             // Cache of the transactions already sorted 
64+ 	cacheMu  sync.Mutex                     // Mutex covering the cache 
6265}
6366
6467// newTxSortedMap creates a new nonce-sorted transaction map. 
@@ -81,7 +84,9 @@ func (m *txSortedMap) Put(tx *types.Transaction) {
8184	if  m .items [nonce ] ==  nil  {
8285		heap .Push (m .index , nonce )
8386	}
87+ 	m .cacheMu .Lock ()
8488	m .items [nonce ], m .cache  =  tx , nil 
89+ 	m .cacheMu .Unlock ()
8590}
8691
8792// Forward removes all transactions from the map with a nonce lower than the 
@@ -97,9 +102,11 @@ func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
97102		delete (m .items , nonce )
98103	}
99104	// If we had a cached order, shift the front 
105+ 	m .cacheMu .Lock ()
100106	if  m .cache  !=  nil  {
101107		m .cache  =  m .cache [len (removed ):]
102108	}
109+ 	m .cacheMu .Unlock ()
103110	return  removed 
104111}
105112
@@ -123,7 +130,9 @@ func (m *txSortedMap) reheap() {
123130		* m .index  =  append (* m .index , nonce )
124131	}
125132	heap .Init (m .index )
133+ 	m .cacheMu .Lock ()
126134	m .cache  =  nil 
135+ 	m .cacheMu .Unlock ()
127136}
128137
129138// filter is identical to Filter, but **does not** regenerate the heap. This method 
@@ -139,7 +148,9 @@ func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transac
139148		}
140149	}
141150	if  len (removed ) >  0  {
151+ 		m .cacheMu .Lock ()
142152		m .cache  =  nil 
153+ 		m .cacheMu .Unlock ()
143154	}
144155	return  removed 
145156}
@@ -153,19 +164,21 @@ func (m *txSortedMap) Cap(threshold int) types.Transactions {
153164	}
154165	// Otherwise gather and drop the highest nonce'd transactions 
155166	var  drops  types.Transactions 
156- 
157- 	sort .Sort (* m .index )
167+ 	slices .Sort (* m .index )
158168	for  size  :=  len (m .items ); size  >  threshold ; size --  {
159169		drops  =  append (drops , m .items [(* m .index )[size - 1 ]])
160170		delete (m .items , (* m .index )[size - 1 ])
161171	}
162172	* m .index  =  (* m .index )[:threshold ]
163- 	heap .Init (m .index )
173+ 	// The sorted m.index slice is still a valid heap, so there is no need to 
174+ 	// reheap after deleting tail items. 
164175
165176	// If we had a cache, shift the back 
177+ 	m .cacheMu .Lock ()
166178	if  m .cache  !=  nil  {
167179		m .cache  =  m .cache [:len (m .cache )- len (drops )]
168180	}
181+ 	m .cacheMu .Unlock ()
169182	return  drops 
170183}
171184
@@ -185,7 +198,9 @@ func (m *txSortedMap) Remove(nonce uint64) bool {
185198		}
186199	}
187200	delete (m .items , nonce )
201+ 	m .cacheMu .Lock ()
188202	m .cache  =  nil 
203+ 	m .cacheMu .Unlock ()
189204
190205	return  true 
191206}
@@ -195,7 +210,7 @@ func (m *txSortedMap) Remove(nonce uint64) bool {
195210// removed from the list. 
196211// 
197212// Note, all transactions with nonces lower than start will also be returned to 
198- // prevent getting into and  invalid state. This is not something that should ever 
213+ // prevent getting into an  invalid state. This is not something that should ever 
199214// happen but better to be self correcting than failing! 
200215func  (m  * txSortedMap ) Ready (start  uint64 ) types.Transactions  {
201216	// Short circuit if no transactions are available 
@@ -209,7 +224,9 @@ func (m *txSortedMap) Ready(start uint64) types.Transactions {
209224		delete (m .items , next )
210225		heap .Pop (m .index )
211226	}
227+ 	m .cacheMu .Lock ()
212228	m .cache  =  nil 
229+ 	m .cacheMu .Unlock ()
213230
214231	return  ready 
215232}
@@ -220,6 +237,8 @@ func (m *txSortedMap) Len() int {
220237}
221238
222239func  (m  * txSortedMap ) flatten () types.Transactions  {
240+ 	m .cacheMu .Lock ()
241+ 	defer  m .cacheMu .Unlock ()
223242	// If the sorting was not cached yet, create and cache it 
224243	if  m .cache  ==  nil  {
225244		m .cache  =  make (types.Transactions , 0 , len (m .items ))
@@ -604,6 +623,7 @@ func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool
604623
605624// Discard finds a number of most underpriced transactions, removes them from the 
606625// priced list and returns them for further removal from the entire pool. 
626+ // If noPending is set to true, we will only consider the floating list 
607627// 
608628// Note local transaction won't be considered for eviction. 
609629func  (l  * txPricedList ) Discard (slots  int , force  bool ) (types.Transactions , bool ) {
0 commit comments