@@ -99,30 +99,7 @@ func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
99
99
100
100
// Filter iterates over the list of transactions and removes all of them for which
101
101
// the specified function evaluates to true.
102
- // Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
103
- // If you want to do several consecutive filterings, it's therefore better to first
104
- // do a .filter(func1) followed by .Filter(func2) or reheap()
105
102
func (m * txSortedMap ) Filter (filter func (* types.Transaction ) bool ) types.Transactions {
106
- removed := m .filter (filter )
107
- // If transactions were removed, the heap and cache are ruined
108
- if len (removed ) > 0 {
109
- m .reheap ()
110
- }
111
- return removed
112
- }
113
-
114
- func (m * txSortedMap ) reheap () {
115
- * m .index = make ([]uint64 , 0 , len (m .items ))
116
- for nonce := range m .items {
117
- * m .index = append (* m .index , nonce )
118
- }
119
- heap .Init (m .index )
120
- m .cache = nil
121
- }
122
-
123
- // filter is identical to Filter, but **does not** regenerate the heap. This method
124
- // should only be used if followed immediately by a call to Filter or reheap()
125
- func (m * txSortedMap ) filter (filter func (* types.Transaction ) bool ) types.Transactions {
126
103
var removed types.Transactions
127
104
128
105
// Collect all the transactions to filter out
@@ -132,7 +109,14 @@ func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transac
132
109
delete (m .items , nonce )
133
110
}
134
111
}
112
+ // If transactions were removed, the heap and cache are ruined
135
113
if len (removed ) > 0 {
114
+ * m .index = make ([]uint64 , 0 , len (m .items ))
115
+ for nonce := range m .items {
116
+ * m .index = append (* m .index , nonce )
117
+ }
118
+ heap .Init (m .index )
119
+
136
120
m .cache = nil
137
121
}
138
122
return removed
@@ -213,7 +197,10 @@ func (m *txSortedMap) Len() int {
213
197
return len (m .items )
214
198
}
215
199
216
- func (m * txSortedMap ) flatten () types.Transactions {
200
+ // Flatten creates a nonce-sorted slice of transactions based on the loosely
201
+ // sorted internal representation. The result of the sorting is cached in case
202
+ // it's requested again before any modifications are made to the contents.
203
+ func (m * txSortedMap ) Flatten () types.Transactions {
217
204
// If the sorting was not cached yet, create and cache it
218
205
if m .cache == nil {
219
206
m .cache = make (types.Transactions , 0 , len (m .items ))
@@ -222,27 +209,12 @@ func (m *txSortedMap) flatten() types.Transactions {
222
209
}
223
210
sort .Sort (types .TxByNonce (m .cache ))
224
211
}
225
- return m .cache
226
- }
227
-
228
- // Flatten creates a nonce-sorted slice of transactions based on the loosely
229
- // sorted internal representation. The result of the sorting is cached in case
230
- // it's requested again before any modifications are made to the contents.
231
- func (m * txSortedMap ) Flatten () types.Transactions {
232
212
// Copy the cache to prevent accidental modifications
233
- cache := m .flatten ()
234
- txs := make (types.Transactions , len (cache ))
235
- copy (txs , cache )
213
+ txs := make (types.Transactions , len (m .cache ))
214
+ copy (txs , m .cache )
236
215
return txs
237
216
}
238
217
239
- // LastElement returns the last element of a flattened list, thus, the
240
- // transaction with the highest nonce
241
- func (m * txSortedMap ) LastElement () * types.Transaction {
242
- cache := m .flatten ()
243
- return cache [len (cache )- 1 ]
244
- }
245
-
246
218
// txList is a "list" of transactions belonging to an account, sorted by account
247
219
// nonce. The same type can be used both for storing contiguous transactions for
248
220
// the executable/pending queue; and for storing gapped transactions for the non-
@@ -251,16 +223,17 @@ type txList struct {
251
223
strict bool // Whether nonces are strictly continuous or not
252
224
txs * txSortedMap // Heap indexed sorted hash map of the transactions
253
225
254
- costcap uint64 // Price of the highest costing transaction (reset only if exceeds balance)
255
- gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
226
+ costcap * big. Int // Price of the highest costing transaction (reset only if exceeds balance)
227
+ gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
256
228
}
257
229
258
230
// newTxList create a new transaction list for maintaining nonce-indexable fast,
259
231
// gapped, sortable transaction lists.
260
232
func newTxList (strict bool ) * txList {
261
233
return & txList {
262
- strict : strict ,
263
- txs : newTxSortedMap (),
234
+ strict : strict ,
235
+ txs : newTxSortedMap (),
236
+ costcap : new (big.Int ),
264
237
}
265
238
}
266
239
@@ -279,26 +252,17 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
279
252
// If there's an older better transaction, abort
280
253
old := l .txs .Get (tx .Nonce ())
281
254
if old != nil {
282
- // threshold = oldGP * (100 + priceBump) / 100
283
- a := big .NewInt (100 + int64 (priceBump ))
284
- a = a .Mul (a , old .GasPrice ())
285
- b := big .NewInt (100 )
286
- threshold := a .Div (a , b )
255
+ threshold := new (big.Int ).Div (new (big.Int ).Mul (old .GasPrice (), big .NewInt (100 + int64 (priceBump ))), big .NewInt (100 ))
287
256
// Have to ensure that the new gas price is higher than the old gas
288
257
// price as well as checking the percentage threshold to ensure that
289
258
// this is accurate for low (Wei-level) gas price replacements
290
259
if old .GasPriceCmp (tx ) >= 0 || tx .GasPriceIntCmp (threshold ) < 0 {
291
260
return false , nil
292
261
}
293
262
}
294
- cost , overflow := tx .CostU64 ()
295
- if overflow {
296
- log .Warn ("transaction cost overflown, txHash: %v txCost: %v" , tx .Hash (), cost )
297
- return false , nil
298
- }
299
263
// Otherwise overwrite the old transaction with the current one
300
264
l .txs .Put (tx )
301
- if l .costcap < cost {
265
+ if cost := tx . Cost (); l .costcap . Cmp ( cost ) < 0 {
302
266
l .costcap = cost
303
267
}
304
268
if gas := tx .Gas (); l .gascap < gas {
@@ -323,35 +287,29 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
323
287
// a point in calculating all the costs or if the balance covers all. If the threshold
324
288
// is lower than the costgas cap, the caps will be reset to a new high after removing
325
289
// the newly invalidated transactions.
326
- func (l * txList ) Filter (costLimit uint64 , gasLimit uint64 ) (types.Transactions , types.Transactions ) {
290
+ func (l * txList ) Filter (costLimit * big. Int , gasLimit uint64 ) (types.Transactions , types.Transactions ) {
327
291
// If all transactions are below the threshold, short circuit
328
- if l .costcap <= costLimit && l .gascap <= gasLimit {
292
+ if l .costcap . Cmp ( costLimit ) <= 0 && l .gascap <= gasLimit {
329
293
return nil , nil
330
294
}
331
- l .costcap = costLimit // Lower the caps to the thresholds
295
+ l .costcap = new (big. Int ). Set ( costLimit ) // Lower the caps to the thresholds
332
296
l .gascap = gasLimit
333
297
334
298
// Filter out all the transactions above the account's funds
335
- removed := l .txs .filter (func (tx * types.Transaction ) bool {
336
- cost , _ := tx .CostU64 ()
337
- return cost > costLimit || tx .Gas () > gasLimit
338
- })
299
+ removed := l .txs .Filter (func (tx * types.Transaction ) bool { return tx .Cost ().Cmp (costLimit ) > 0 || tx .Gas () > gasLimit })
339
300
340
- if len (removed ) == 0 {
341
- return nil , nil
342
- }
343
- var invalids types.Transactions
344
301
// If the list was strict, filter anything above the lowest nonce
345
- if l .strict {
302
+ var invalids types.Transactions
303
+
304
+ if l .strict && len (removed ) > 0 {
346
305
lowest := uint64 (math .MaxUint64 )
347
306
for _ , tx := range removed {
348
307
if nonce := tx .Nonce (); lowest > nonce {
349
308
lowest = nonce
350
309
}
351
310
}
352
- invalids = l .txs .filter (func (tx * types.Transaction ) bool { return tx .Nonce () > lowest })
311
+ invalids = l .txs .Filter (func (tx * types.Transaction ) bool { return tx .Nonce () > lowest })
353
312
}
354
- l .txs .reheap ()
355
313
return removed , invalids
356
314
}
357
315
@@ -405,12 +363,6 @@ func (l *txList) Flatten() types.Transactions {
405
363
return l .txs .Flatten ()
406
364
}
407
365
408
- // LastElement returns the last element of a flattened list, thus, the
409
- // transaction with the highest nonce
410
- func (l * txList ) LastElement () * types.Transaction {
411
- return l .txs .LastElement ()
412
- }
413
-
414
366
// priceHeap is a heap.Interface implementation over transactions for retrieving
415
367
// price-sorted transactions to discard when the pool fills up.
416
368
type priceHeap []* types.Transaction
@@ -543,29 +495,8 @@ func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) boo
543
495
// Discard finds a number of most underpriced transactions, removes them from the
544
496
// priced list and returns them for further removal from the entire pool.
545
497
func (l * txPricedList ) Discard (slots int , local * accountSet ) types.Transactions {
546
- // If we have some local accountset, those will not be discarded
547
- if ! local .empty () {
548
- // In case the list is filled to the brim with 'local' txs, we do this
549
- // little check to avoid unpacking / repacking the heap later on, which
550
- // is very expensive
551
- discardable := 0
552
- for _ , tx := range * l .items {
553
- if ! local .containsTx (tx ) {
554
- discardable ++
555
- }
556
- if discardable >= slots {
557
- break
558
- }
559
- }
560
- if slots > discardable {
561
- slots = discardable
562
- }
563
- }
564
- if slots == 0 {
565
- return nil
566
- }
567
- drop := make (types.Transactions , 0 , slots ) // Remote underpriced transactions to drop
568
- save := make (types.Transactions , 0 , len (* l .items )- slots ) // Local underpriced transactions to keep
498
+ drop := make (types.Transactions , 0 , slots ) // Remote underpriced transactions to drop
499
+ save := make (types.Transactions , 0 , 64 ) // Local underpriced transactions to keep
569
500
570
501
for len (* l .items ) > 0 && slots > 0 {
571
502
// Discard stale transactions if found during cleanup
0 commit comments