tx_list.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  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) Less(i, j int) bool { return h[i].GasPrice().Cmp(h[j].GasPrice()) < 0 }
  329. func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
  330. func (h *priceHeap) Push(x interface{}) {
  331. *h = append(*h, x.(*types.Transaction))
  332. }
  333. func (h *priceHeap) Pop() interface{} {
  334. old := *h
  335. n := len(old)
  336. x := old[n-1]
  337. *h = old[0 : n-1]
  338. return x
  339. }
  340. // txPricedList is a price-sorted heap to allow operating on transactions pool
  341. // contents in a price-incrementing way.
  342. type txPricedList struct {
  343. all *map[common.Hash]*types.Transaction // Pointer to the map of all transactions
  344. items *priceHeap // Heap of prices of all the stored transactions
  345. stales int // Number of stale price points to (re-heap trigger)
  346. }
  347. // newTxPricedList creates a new price-sorted transaction heap.
  348. func newTxPricedList(all *map[common.Hash]*types.Transaction) *txPricedList {
  349. return &txPricedList{
  350. all: all,
  351. items: new(priceHeap),
  352. }
  353. }
  354. // Put inserts a new transaction into the heap.
  355. func (l *txPricedList) Put(tx *types.Transaction) {
  356. heap.Push(l.items, tx)
  357. }
  358. // Removed notifies the prices transaction list that an old transaction dropped
  359. // from the pool. The list will just keep a counter of stale objects and update
  360. // the heap if a large enough ratio of transactions go stale.
  361. func (l *txPricedList) Removed() {
  362. // Bump the stale counter, but exit if still too low (< 25%)
  363. l.stales++
  364. if l.stales <= len(*l.items)/4 {
  365. return
  366. }
  367. // Seems we've reached a critical number of stale transactions, reheap
  368. reheap := make(priceHeap, 0, len(*l.all))
  369. l.stales, l.items = 0, &reheap
  370. for _, tx := range *l.all {
  371. *l.items = append(*l.items, tx)
  372. }
  373. heap.Init(l.items)
  374. }
  375. // Cap finds all the transactions below the given price threshold, drops them
  376. // from the priced list and returs them for further removal from the entire pool.
  377. func (l *txPricedList) Cap(threshold *big.Int, local *accountSet) types.Transactions {
  378. drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop
  379. save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
  380. for len(*l.items) > 0 {
  381. // Discard stale transactions if found during cleanup
  382. tx := heap.Pop(l.items).(*types.Transaction)
  383. if _, ok := (*l.all)[tx.Hash()]; !ok {
  384. l.stales--
  385. continue
  386. }
  387. // Stop the discards if we've reached the threshold
  388. if tx.GasPrice().Cmp(threshold) >= 0 {
  389. save = append(save, tx)
  390. break
  391. }
  392. // Non stale transaction found, discard unless local
  393. if local.containsTx(tx) {
  394. save = append(save, tx)
  395. } else {
  396. drop = append(drop, tx)
  397. }
  398. }
  399. for _, tx := range save {
  400. heap.Push(l.items, tx)
  401. }
  402. return drop
  403. }
  404. // Underpriced checks whether a transaction is cheaper than (or as cheap as) the
  405. // lowest priced transaction currently being tracked.
  406. func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) bool {
  407. // Local transactions cannot be underpriced
  408. if local.containsTx(tx) {
  409. return false
  410. }
  411. // Discard stale price points if found at the heap start
  412. for len(*l.items) > 0 {
  413. head := []*types.Transaction(*l.items)[0]
  414. if _, ok := (*l.all)[head.Hash()]; !ok {
  415. l.stales--
  416. heap.Pop(l.items)
  417. continue
  418. }
  419. break
  420. }
  421. // Check if the transaction is underpriced or not
  422. if len(*l.items) == 0 {
  423. log.Error("Pricing query for empty pool") // This cannot happen, print to catch programming errors
  424. return false
  425. }
  426. cheapest := []*types.Transaction(*l.items)[0]
  427. return cheapest.GasPrice().Cmp(tx.GasPrice()) >= 0
  428. }
  429. // Discard finds a number of most underpriced transactions, removes them from the
  430. // priced list and returns them for further removal from the entire pool.
  431. func (l *txPricedList) Discard(count int, local *accountSet) types.Transactions {
  432. drop := make(types.Transactions, 0, count) // Remote underpriced transactions to drop
  433. save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep
  434. for len(*l.items) > 0 && count > 0 {
  435. // Discard stale transactions if found during cleanup
  436. tx := heap.Pop(l.items).(*types.Transaction)
  437. if _, ok := (*l.all)[tx.Hash()]; !ok {
  438. l.stales--
  439. continue
  440. }
  441. // Non stale transaction found, discard unless local
  442. if local.containsTx(tx) {
  443. save = append(save, tx)
  444. } else {
  445. drop = append(drop, tx)
  446. count--
  447. }
  448. }
  449. for _, tx := range save {
  450. heap.Push(l.items, tx)
  451. }
  452. return drop
  453. }