tx_list.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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. package core
  17. import (
  18. "container/heap"
  19. "math"
  20. "math/big"
  21. "sort"
  22. "github.com/ethereum/go-ethereum/common"
  23. "github.com/ethereum/go-ethereum/core/types"
  24. )
  25. // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
  26. // retrieving sorted transactions from the possibly gapped future queue.
  27. type nonceHeap []uint64
  28. func (h nonceHeap) Len() int { return len(h) }
  29. func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] }
  30. func (h nonceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
  31. func (h *nonceHeap) Push(x interface{}) {
  32. *h = append(*h, x.(uint64))
  33. }
  34. func (h *nonceHeap) Pop() interface{} {
  35. old := *h
  36. n := len(old)
  37. x := old[n-1]
  38. *h = old[0 : n-1]
  39. return x
  40. }
  41. // txSortedMap is a nonce->transaction hash map with a heap based index to allow
  42. // iterating over the contents in a nonce-incrementing way.
  43. type txSortedMap struct {
  44. items map[uint64]*types.Transaction // Hash map storing the transaction data
  45. index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode)
  46. cache types.Transactions // Cache of the transactions already sorted
  47. }
  48. // newTxSortedMap creates a new nonce-sorted transaction map.
  49. func newTxSortedMap() *txSortedMap {
  50. return &txSortedMap{
  51. items: make(map[uint64]*types.Transaction),
  52. index: new(nonceHeap),
  53. }
  54. }
  55. // Get retrieves the current transactions associated with the given nonce.
  56. func (m *txSortedMap) Get(nonce uint64) *types.Transaction {
  57. return m.items[nonce]
  58. }
  59. // Put inserts a new transaction into the map, also updating the map's nonce
  60. // index. If a transaction already exists with the same nonce, it's overwritten.
  61. func (m *txSortedMap) Put(tx *types.Transaction) {
  62. nonce := tx.Nonce()
  63. if m.items[nonce] == nil {
  64. heap.Push(m.index, nonce)
  65. }
  66. m.items[nonce], m.cache = tx, nil
  67. }
  68. // Forward removes all transactions from the map with a nonce lower than the
  69. // provided threshold. Every removed transaction is returned for any post-removal
  70. // maintenance.
  71. func (m *txSortedMap) Forward(threshold uint64) types.Transactions {
  72. var removed types.Transactions
  73. // Pop off heap items until the threshold is reached
  74. for m.index.Len() > 0 && (*m.index)[0] < threshold {
  75. nonce := heap.Pop(m.index).(uint64)
  76. removed = append(removed, m.items[nonce])
  77. delete(m.items, nonce)
  78. }
  79. // If we had a cached order, shift the front
  80. if m.cache != nil {
  81. m.cache = m.cache[len(removed):]
  82. }
  83. return removed
  84. }
  85. // Filter iterates over the list of transactions and removes all of them for which
  86. // the specified function evaluates to true.
  87. // Filter, as opposed to 'filter', re-initialises the heap after the operation is done.
  88. // If you want to do several consecutive filterings, it's therefore better to first
  89. // do a .filter(func1) followed by .Filter(func2) or reheap()
  90. func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions {
  91. removed := m.filter(filter)
  92. // If transactions were removed, the heap and cache are ruined
  93. if len(removed) > 0 {
  94. m.reheap()
  95. }
  96. return removed
  97. }
  98. func (m *txSortedMap) reheap() {
  99. *m.index = make([]uint64, 0, len(m.items))
  100. for nonce := range m.items {
  101. *m.index = append(*m.index, nonce)
  102. }
  103. heap.Init(m.index)
  104. m.cache = nil
  105. }
  106. // filter is identical to Filter, but **does not** regenerate the heap. This method
  107. // should only be used if followed immediately by a call to Filter or reheap()
  108. func (m *txSortedMap) filter(filter func(*types.Transaction) bool) types.Transactions {
  109. var removed types.Transactions
  110. // Collect all the transactions to filter out
  111. for nonce, tx := range m.items {
  112. if filter(tx) {
  113. removed = append(removed, tx)
  114. delete(m.items, nonce)
  115. }
  116. }
  117. if len(removed) > 0 {
  118. m.cache = nil
  119. }
  120. return removed
  121. }
  122. // Cap places a hard limit on the number of items, returning all transactions
  123. // exceeding that limit.
  124. func (m *txSortedMap) Cap(threshold int) types.Transactions {
  125. // Short circuit if the number of items is under the limit
  126. if len(m.items) <= threshold {
  127. return nil
  128. }
  129. // Otherwise gather and drop the highest nonce'd transactions
  130. var drops types.Transactions
  131. sort.Sort(*m.index)
  132. for size := len(m.items); size > threshold; size-- {
  133. drops = append(drops, m.items[(*m.index)[size-1]])
  134. delete(m.items, (*m.index)[size-1])
  135. }
  136. *m.index = (*m.index)[:threshold]
  137. heap.Init(m.index)
  138. // If we had a cache, shift the back
  139. if m.cache != nil {
  140. m.cache = m.cache[:len(m.cache)-len(drops)]
  141. }
  142. return drops
  143. }
  144. // Remove deletes a transaction from the maintained map, returning whether the
  145. // transaction was found.
  146. func (m *txSortedMap) Remove(nonce uint64) bool {
  147. // Short circuit if no transaction is present
  148. _, ok := m.items[nonce]
  149. if !ok {
  150. return false
  151. }
  152. // Otherwise delete the transaction and fix the heap index
  153. for i := 0; i < m.index.Len(); i++ {
  154. if (*m.index)[i] == nonce {
  155. heap.Remove(m.index, i)
  156. break
  157. }
  158. }
  159. delete(m.items, nonce)
  160. m.cache = nil
  161. return true
  162. }
  163. // Ready retrieves a sequentially increasing list of transactions starting at the
  164. // provided nonce that is ready for processing. The returned transactions will be
  165. // removed from the list.
  166. //
  167. // Note, all transactions with nonces lower than start will also be returned to
  168. // prevent getting into and invalid state. This is not something that should ever
  169. // happen but better to be self correcting than failing!
  170. func (m *txSortedMap) Ready(start uint64) types.Transactions {
  171. // Short circuit if no transactions are available
  172. if m.index.Len() == 0 || (*m.index)[0] > start {
  173. return nil
  174. }
  175. // Otherwise start accumulating incremental transactions
  176. var ready types.Transactions
  177. for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ {
  178. ready = append(ready, m.items[next])
  179. delete(m.items, next)
  180. heap.Pop(m.index)
  181. }
  182. m.cache = nil
  183. return ready
  184. }
  185. // Len returns the length of the transaction map.
  186. func (m *txSortedMap) Len() int {
  187. return len(m.items)
  188. }
  189. func (m *txSortedMap) flatten() types.Transactions {
  190. // If the sorting was not cached yet, create and cache it
  191. if m.cache == nil {
  192. m.cache = make(types.Transactions, 0, len(m.items))
  193. for _, tx := range m.items {
  194. m.cache = append(m.cache, tx)
  195. }
  196. sort.Sort(types.TxByNonce(m.cache))
  197. }
  198. return m.cache
  199. }
  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 {
  204. // Copy the cache to prevent accidental modifications
  205. cache := m.flatten()
  206. txs := make(types.Transactions, len(cache))
  207. copy(txs, cache)
  208. return txs
  209. }
  210. // LastElement returns the last element of a flattened list, thus, the
  211. // transaction with the highest nonce
  212. func (m *txSortedMap) LastElement() *types.Transaction {
  213. cache := m.flatten()
  214. return cache[len(cache)-1]
  215. }
  216. // txList is a "list" of transactions belonging to an account, sorted by account
  217. // nonce. The same type can be used both for storing contiguous transactions for
  218. // the executable/pending queue; and for storing gapped transactions for the non-
  219. // executable/future queue, with minor behavioral changes.
  220. type txList struct {
  221. strict bool // Whether nonces are strictly continuous or not
  222. txs *txSortedMap // Heap indexed sorted hash map of the transactions
  223. costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
  224. gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
  225. }
  226. // newTxList create a new transaction list for maintaining nonce-indexable fast,
  227. // gapped, sortable transaction lists.
  228. func newTxList(strict bool) *txList {
  229. return &txList{
  230. strict: strict,
  231. txs: newTxSortedMap(),
  232. costcap: new(big.Int),
  233. }
  234. }
  235. // Overlaps returns whether the transaction specified has the same nonce as one
  236. // already contained within the list.
  237. func (l *txList) Overlaps(tx *types.Transaction) bool {
  238. return l.txs.Get(tx.Nonce()) != nil
  239. }
  240. // Add tries to insert a new transaction into the list, returning whether the
  241. // transaction was accepted, and if yes, any previous transaction it replaced.
  242. //
  243. // If the new transaction is accepted into the list, the lists' cost and gas
  244. // thresholds are also potentially updated.
  245. func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
  246. // If there's an older better transaction, abort
  247. old := l.txs.Get(tx.Nonce())
  248. if old != nil {
  249. // threshold = oldGP * (100 + priceBump) / 100
  250. a := big.NewInt(100 + int64(priceBump))
  251. a = a.Mul(a, old.GasPrice())
  252. b := big.NewInt(100)
  253. threshold := a.Div(a, b)
  254. // Have to ensure that the new gas price is higher than the old gas
  255. // price as well as checking the percentage threshold to ensure that
  256. // this is accurate for low (Wei-level) gas price replacements
  257. if old.GasPriceCmp(tx) >= 0 || tx.GasPriceIntCmp(threshold) < 0 {
  258. return false, nil
  259. }
  260. }
  261. // Otherwise overwrite the old transaction with the current one
  262. l.txs.Put(tx)
  263. if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
  264. l.costcap = cost
  265. }
  266. if gas := tx.Gas(); l.gascap < gas {
  267. l.gascap = gas
  268. }
  269. return true, old
  270. }
  271. // Forward removes all transactions from the list with a nonce lower than the
  272. // provided threshold. Every removed transaction is returned for any post-removal
  273. // maintenance.
  274. func (l *txList) Forward(threshold uint64) types.Transactions {
  275. return l.txs.Forward(threshold)
  276. }
  277. // Filter removes all transactions from the list with a cost or gas limit higher
  278. // than the provided thresholds. Every removed transaction is returned for any
  279. // post-removal maintenance. Strict-mode invalidated transactions are also
  280. // returned.
  281. //
  282. // This method uses the cached costcap and gascap to quickly decide if there's even
  283. // a point in calculating all the costs or if the balance covers all. If the threshold
  284. // is lower than the costgas cap, the caps will be reset to a new high after removing
  285. // the newly invalidated transactions.
  286. func (l *txList) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
  287. // If all transactions are below the threshold, short circuit
  288. if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
  289. return nil, nil
  290. }
  291. l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
  292. l.gascap = gasLimit
  293. // Filter out all the transactions above the account's funds
  294. removed := l.txs.Filter(func(tx *types.Transaction) bool {
  295. return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit) > 0
  296. })
  297. if len(removed) == 0 {
  298. return nil, nil
  299. }
  300. var invalids types.Transactions
  301. // If the list was strict, filter anything above the lowest nonce
  302. if l.strict {
  303. lowest := uint64(math.MaxUint64)
  304. for _, tx := range removed {
  305. if nonce := tx.Nonce(); lowest > nonce {
  306. lowest = nonce
  307. }
  308. }
  309. invalids = l.txs.filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest })
  310. }
  311. l.txs.reheap()
  312. return removed, invalids
  313. }
  314. // Cap places a hard limit on the number of items, returning all transactions
  315. // exceeding that limit.
  316. func (l *txList) Cap(threshold int) types.Transactions {
  317. return l.txs.Cap(threshold)
  318. }
  319. // Remove deletes a transaction from the maintained list, returning whether the
  320. // transaction was found, and also returning any transaction invalidated due to
  321. // the deletion (strict mode only).
  322. func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) {
  323. // Remove the transaction from the set
  324. nonce := tx.Nonce()
  325. if removed := l.txs.Remove(nonce); !removed {
  326. return false, nil
  327. }
  328. // In strict mode, filter out non-executable transactions
  329. if l.strict {
  330. return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce })
  331. }
  332. return true, nil
  333. }
  334. // Ready retrieves a sequentially increasing list of transactions starting at the
  335. // provided nonce that is ready for processing. The returned transactions will be
  336. // removed from the list.
  337. //
  338. // Note, all transactions with nonces lower than start will also be returned to
  339. // prevent getting into and invalid state. This is not something that should ever
  340. // happen but better to be self correcting than failing!
  341. func (l *txList) Ready(start uint64) types.Transactions {
  342. return l.txs.Ready(start)
  343. }
  344. // Len returns the length of the transaction list.
  345. func (l *txList) Len() int {
  346. return l.txs.Len()
  347. }
  348. // Empty returns whether the list of transactions is empty or not.
  349. func (l *txList) Empty() bool {
  350. return l.Len() == 0
  351. }
  352. // Flatten creates a nonce-sorted slice of transactions based on the loosely
  353. // sorted internal representation. The result of the sorting is cached in case
  354. // it's requested again before any modifications are made to the contents.
  355. func (l *txList) Flatten() types.Transactions {
  356. return l.txs.Flatten()
  357. }
  358. // LastElement returns the last element of a flattened list, thus, the
  359. // transaction with the highest nonce
  360. func (l *txList) LastElement() *types.Transaction {
  361. return l.txs.LastElement()
  362. }
  363. // priceHeap is a heap.Interface implementation over transactions for retrieving
  364. // price-sorted transactions to discard when the pool fills up.
  365. type priceHeap []*types.Transaction
  366. func (h priceHeap) Len() int { return len(h) }
  367. func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
  368. func (h priceHeap) Less(i, j int) bool {
  369. // Sort primarily by price, returning the cheaper one
  370. switch h[i].GasPriceCmp(h[j]) {
  371. case -1:
  372. return true
  373. case 1:
  374. return false
  375. }
  376. // If the prices match, stabilize via nonces (high nonce is worse)
  377. return h[i].Nonce() > h[j].Nonce()
  378. }
  379. func (h *priceHeap) Push(x interface{}) {
  380. *h = append(*h, x.(*types.Transaction))
  381. }
  382. func (h *priceHeap) Pop() interface{} {
  383. old := *h
  384. n := len(old)
  385. x := old[n-1]
  386. old[n-1] = nil
  387. *h = old[0 : n-1]
  388. return x
  389. }
  390. // txPricedList is a price-sorted heap to allow operating on transactions pool
  391. // contents in a price-incrementing way. It's built opon the all transactions
  392. // in txpool but only interested in the remote part. It means only remote transactions
  393. // will be considered for tracking, sorting, eviction, etc.
  394. type txPricedList struct {
  395. all *txLookup // Pointer to the map of all transactions
  396. remotes *priceHeap // Heap of prices of all the stored **remote** transactions
  397. stales int // Number of stale price points to (re-heap trigger)
  398. }
  399. // newTxPricedList creates a new price-sorted transaction heap.
  400. func newTxPricedList(all *txLookup) *txPricedList {
  401. return &txPricedList{
  402. all: all,
  403. remotes: new(priceHeap),
  404. }
  405. }
  406. // Put inserts a new transaction into the heap.
  407. func (l *txPricedList) Put(tx *types.Transaction, local bool) {
  408. if local {
  409. return
  410. }
  411. heap.Push(l.remotes, tx)
  412. }
  413. // Removed notifies the prices transaction list that an old transaction dropped
  414. // from the pool. The list will just keep a counter of stale objects and update
  415. // the heap if a large enough ratio of transactions go stale.
  416. func (l *txPricedList) Removed(count int) {
  417. // Bump the stale counter, but exit if still too low (< 25%)
  418. l.stales += count
  419. if l.stales <= len(*l.remotes)/4 {
  420. return
  421. }
  422. // Seems we've reached a critical number of stale transactions, reheap
  423. l.Reheap()
  424. }
  425. // Cap finds all the transactions below the given price threshold, drops them
  426. // from the priced list and returns them for further removal from the entire pool.
  427. //
  428. // Note: only remote transactions will be considered for eviction.
  429. func (l *txPricedList) Cap(threshold *big.Int) types.Transactions {
  430. drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
  431. for len(*l.remotes) > 0 {
  432. // Discard stale transactions if found during cleanup
  433. cheapest := (*l.remotes)[0]
  434. if l.all.GetRemote(cheapest.Hash()) == nil { // Removed or migrated
  435. heap.Pop(l.remotes)
  436. l.stales--
  437. continue
  438. }
  439. // Stop the discards if we've reached the threshold
  440. if cheapest.GasPriceIntCmp(threshold) >= 0 {
  441. break
  442. }
  443. heap.Pop(l.remotes)
  444. drop = append(drop, cheapest)
  445. }
  446. return drop
  447. }
  448. // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
  449. // lowest priced (remote) transaction currently being tracked.
  450. func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
  451. // Discard stale price points if found at the heap start
  452. for len(*l.remotes) > 0 {
  453. head := []*types.Transaction(*l.remotes)[0]
  454. if l.all.GetRemote(head.Hash()) == nil { // Removed or migrated
  455. l.stales--
  456. heap.Pop(l.remotes)
  457. continue
  458. }
  459. break
  460. }
  461. // Check if the transaction is underpriced or not
  462. if len(*l.remotes) == 0 {
  463. return false // There is no remote transaction at all.
  464. }
  465. // If the remote transaction is even cheaper than the
  466. // cheapest one tracked locally, reject it.
  467. cheapest := []*types.Transaction(*l.remotes)[0]
  468. return cheapest.GasPriceCmp(tx) >= 0
  469. }
  470. // Discard finds a number of most underpriced transactions, removes them from the
  471. // priced list and returns them for further removal from the entire pool.
  472. //
  473. // Note local transaction won't be considered for eviction.
  474. func (l *txPricedList) Discard(slots int, force bool) (types.Transactions, bool) {
  475. drop := make(types.Transactions, 0, slots) // Remote underpriced transactions to drop
  476. for len(*l.remotes) > 0 && slots > 0 {
  477. // Discard stale transactions if found during cleanup
  478. tx := heap.Pop(l.remotes).(*types.Transaction)
  479. if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
  480. l.stales--
  481. continue
  482. }
  483. // Non stale transaction found, discard it
  484. drop = append(drop, tx)
  485. slots -= numSlots(tx)
  486. }
  487. // If we still can't make enough room for the new transaction
  488. if slots > 0 && !force {
  489. for _, tx := range drop {
  490. heap.Push(l.remotes, tx)
  491. }
  492. return nil, false
  493. }
  494. return drop, true
  495. }
  496. // Reheap forcibly rebuilds the heap based on the current remote transaction set.
  497. func (l *txPricedList) Reheap() {
  498. reheap := make(priceHeap, 0, l.all.RemoteCount())
  499. l.stales, l.remotes = 0, &reheap
  500. l.all.Range(func(hash common.Hash, tx *types.Transaction, local bool) bool {
  501. *l.remotes = append(*l.remotes, tx)
  502. return true
  503. }, false, true) // Only iterate remotes
  504. heap.Init(l.remotes)
  505. }