tx_list.go 17 KB

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