github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/core/tx_list.go (about) 1 // Copyright 2018 Wanchain Foundation Ltd 2 // Copyright 2016 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 18 package core 19 20 import ( 21 "container/heap" 22 "math" 23 "math/big" 24 "sort" 25 26 "github.com/wanchain/go-wanchain/common" 27 "github.com/wanchain/go-wanchain/core/types" 28 "github.com/wanchain/go-wanchain/core/vm" 29 "github.com/wanchain/go-wanchain/log" 30 ) 31 32 // nonceHeap is a heap.Interface implementation over 64bit unsigned integers for 33 // retrieving sorted transactions from the possibly gapped future queue. 34 type nonceHeap []uint64 35 36 func (h nonceHeap) Len() int { return len(h) } 37 func (h nonceHeap) Less(i, j int) bool { return h[i] < h[j] } 38 func (h nonceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 39 40 func (h *nonceHeap) Push(x interface{}) { 41 *h = append(*h, x.(uint64)) 42 } 43 44 func (h *nonceHeap) Pop() interface{} { 45 old := *h 46 n := len(old) 47 x := old[n-1] 48 *h = old[0 : n-1] 49 return x 50 } 51 52 // txSortedMap is a nonce->transaction hash map with a heap based index to allow 53 // iterating over the contents in a nonce-incrementing way. 54 type txSortedMap struct { 55 items map[uint64]*types.Transaction // Hash map storing the transaction data 56 index *nonceHeap // Heap of nonces of all the stored transactions (non-strict mode) 57 cache types.Transactions // Cache of the transactions already sorted 58 } 59 60 // newTxSortedMap creates a new nonce-sorted transaction map. 61 func newTxSortedMap() *txSortedMap { 62 return &txSortedMap{ 63 items: make(map[uint64]*types.Transaction), 64 index: new(nonceHeap), 65 } 66 } 67 68 // Get retrieves the current transactions associated with the given nonce. 69 func (m *txSortedMap) Get(nonce uint64) *types.Transaction { 70 return m.items[nonce] 71 } 72 73 // Put inserts a new transaction into the map, also updating the map's nonce 74 // index. If a transaction already exists with the same nonce, it's overwritten. 75 func (m *txSortedMap) Put(tx *types.Transaction) { 76 nonce := tx.Nonce() 77 if m.items[nonce] == nil { 78 heap.Push(m.index, nonce) 79 } 80 m.items[nonce], m.cache = tx, nil 81 } 82 83 // Forward removes all transactions from the map with a nonce lower than the 84 // provided threshold. Every removed transaction is returned for any post-removal 85 // maintenance. 86 func (m *txSortedMap) Forward(threshold uint64) types.Transactions { 87 var removed types.Transactions 88 89 // Pop off heap items until the threshold is reached 90 for m.index.Len() > 0 && (*m.index)[0] < threshold { 91 nonce := heap.Pop(m.index).(uint64) 92 removed = append(removed, m.items[nonce]) 93 delete(m.items, nonce) 94 } 95 // If we had a cached order, shift the front 96 if m.cache != nil { 97 m.cache = m.cache[len(removed):] 98 } 99 return removed 100 } 101 102 // Filter iterates over the list of transactions and removes all of them for which 103 // the specified function evaluates to true. 104 func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transactions { 105 var removed types.Transactions 106 107 // Collect all the transactions to filter out 108 for nonce, tx := range m.items { 109 if filter(tx) { 110 removed = append(removed, tx) 111 delete(m.items, nonce) 112 } 113 } 114 // If transactions were removed, the heap and cache are ruined 115 if len(removed) > 0 { 116 *m.index = make([]uint64, 0, len(m.items)) 117 for nonce := range m.items { 118 *m.index = append(*m.index, nonce) 119 } 120 heap.Init(m.index) 121 122 m.cache = nil 123 } 124 return removed 125 } 126 127 // Cap places a hard limit on the number of items, returning all transactions 128 // exceeding that limit. 129 func (m *txSortedMap) Cap(threshold int) types.Transactions { 130 // Short circuit if the number of items is under the limit 131 if len(m.items) <= threshold { 132 return nil 133 } 134 // Otherwise gather and drop the highest nonce'd transactions 135 var drops types.Transactions 136 137 sort.Sort(*m.index) 138 for size := len(m.items); size > threshold; size-- { 139 drops = append(drops, m.items[(*m.index)[size-1]]) 140 delete(m.items, (*m.index)[size-1]) 141 } 142 *m.index = (*m.index)[:threshold] 143 heap.Init(m.index) 144 145 // If we had a cache, shift the back 146 if m.cache != nil { 147 m.cache = m.cache[:len(m.cache)-len(drops)] 148 } 149 return drops 150 } 151 152 // Remove deletes a transaction from the maintained map, returning whether the 153 // transaction was found. 154 func (m *txSortedMap) Remove(nonce uint64) bool { 155 // Short circuit if no transaction is present 156 _, ok := m.items[nonce] 157 if !ok { 158 return false 159 } 160 // Otherwise delete the transaction and fix the heap index 161 for i := 0; i < m.index.Len(); i++ { 162 if (*m.index)[i] == nonce { 163 heap.Remove(m.index, i) 164 break 165 } 166 } 167 delete(m.items, nonce) 168 m.cache = nil 169 170 return true 171 } 172 173 // Ready retrieves a sequentially increasing list of transactions starting at the 174 // provided nonce that is ready for processing. The returned transactions will be 175 // removed from the list. 176 // 177 // Note, all transactions with nonces lower than start will also be returned to 178 // prevent getting into and invalid state. This is not something that should ever 179 // happen but better to be self correcting than failing! 180 func (m *txSortedMap) Ready(start uint64) types.Transactions { 181 // Short circuit if no transactions are available 182 if m.index.Len() == 0 || (*m.index)[0] > start { 183 return nil 184 } 185 // Otherwise start accumulating incremental transactions 186 var ready types.Transactions 187 for next := (*m.index)[0]; m.index.Len() > 0 && (*m.index)[0] == next; next++ { 188 ready = append(ready, m.items[next]) 189 delete(m.items, next) 190 heap.Pop(m.index) 191 } 192 m.cache = nil 193 194 return ready 195 } 196 197 // Len returns the length of the transaction map. 198 func (m *txSortedMap) Len() int { 199 return len(m.items) 200 } 201 202 // Flatten creates a nonce-sorted slice of transactions based on the loosely 203 // sorted internal representation. The result of the sorting is cached in case 204 // it's requested again before any modifications are made to the contents. 205 func (m *txSortedMap) Flatten() types.Transactions { 206 // If the sorting was not cached yet, create and cache it 207 if m.cache == nil { 208 m.cache = make(types.Transactions, 0, len(m.items)) 209 for _, tx := range m.items { 210 m.cache = append(m.cache, tx) 211 } 212 sort.Sort(types.TxByNonce(m.cache)) 213 } 214 // Copy the cache to prevent accidental modifications 215 txs := make(types.Transactions, len(m.cache)) 216 copy(txs, m.cache) 217 return txs 218 } 219 220 // txList is a "list" of transactions belonging to an account, sorted by account 221 // nonce. The same type can be used both for storing contiguous transactions for 222 // the executable/pending queue; and for storing gapped transactions for the non- 223 // executable/future queue, with minor behavioral changes. 224 type txList struct { 225 strict bool // Whether nonces are strictly continuous or not 226 txs *txSortedMap // Heap indexed sorted hash map of the transactions 227 228 costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance) 229 gascap *big.Int // Gas limit of the highest spending transaction (reset only if exceeds block limit) 230 } 231 232 // newTxList create a new transaction list for maintaining nonce-indexable fast, 233 // gapped, sortable transaction lists. 234 func newTxList(strict bool) *txList { 235 return &txList{ 236 strict: strict, 237 txs: newTxSortedMap(), 238 costcap: new(big.Int), 239 gascap: new(big.Int), 240 } 241 } 242 243 // Overlaps returns whether the transaction specified has the same nonce as one 244 // already contained within the list. 245 func (l *txList) Overlaps(tx *types.Transaction) bool { 246 return l.txs.Get(tx.Nonce()) != nil 247 } 248 249 // Add tries to insert a new transaction into the list, returning whether the 250 // transaction was accepted, and if yes, any previous transaction it replaced. 251 // 252 // If the new transaction is accepted into the list, the lists' cost and gas 253 // thresholds are also potentially updated. 254 func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) { 255 // If there's an older better transaction, abort 256 old := l.txs.Get(tx.Nonce()) 257 if old != nil { 258 threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100)) 259 if threshold.Cmp(tx.GasPrice()) >= 0 { 260 return false, nil 261 } 262 } 263 // Otherwise overwrite the old transaction with the current one 264 l.txs.Put(tx) 265 if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 { 266 l.costcap = cost 267 } 268 if gas := tx.Gas(); l.gascap.Cmp(gas) < 0 { 269 l.gascap = gas 270 } 271 return true, old 272 } 273 274 // Forward removes all transactions from the list with a nonce lower than the 275 // provided threshold. Every removed transaction is returned for any post-removal 276 // maintenance. 277 func (l *txList) Forward(threshold uint64) types.Transactions { 278 return l.txs.Forward(threshold) 279 } 280 281 // Filter removes all transactions from the list with a cost or gas limit higher 282 // than the provided thresholds. Every removed transaction is returned for any 283 // post-removal maintenance. Strict-mode invalidated transactions are also 284 // returned. 285 // 286 // This method uses the cached costcap and gascap to quickly decide if there's even 287 // a point in calculating all the costs or if the balance covers all. If the threshold 288 // is lower than the costgas cap, the caps will be reset to a new high after removing 289 // the newly invalidated transactions. 290 func (l *txList) Filter(costLimit, gasLimit *big.Int) (types.Transactions, types.Transactions) { 291 // If all transactions are below the threshold, short circuit 292 if l.costcap.Cmp(costLimit) <= 0 && l.gascap.Cmp(gasLimit) <= 0 { 293 return nil, nil 294 } 295 l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds 296 l.gascap = new(big.Int).Set(gasLimit) 297 298 // Filter out all the transactions above the account's funds 299 removed := l.txs.Filter(func(tx *types.Transaction) bool { 300 return types.IsNormalTransaction(tx.Txtype()) && (tx.Cost().Cmp(costLimit) > 0 || tx.Gas().Cmp(gasLimit) > 0) 301 }) 302 303 // If the list was strict, filter anything above the lowest nonce 304 var invalids types.Transactions 305 306 if l.strict && len(removed) > 0 { 307 lowest := uint64(math.MaxUint64) 308 for _, tx := range removed { 309 if nonce := tx.Nonce(); lowest > nonce { 310 lowest = nonce 311 } 312 } 313 invalids = l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) 314 } 315 return removed, invalids 316 } 317 318 // InvalidPrivacyTx remove invalidate privacy transactions 319 func (l *txList) InvalidPrivacyTx(stateDB vm.StateDB, signer types.Signer, gasLimit *big.Int) types.Transactions { 320 removed := l.txs.Filter(func(tx *types.Transaction) bool { 321 if types.IsNormalTransaction(tx.Txtype()) { 322 return false 323 } 324 325 from, err := types.Sender(signer, tx) 326 if err != nil { 327 return true 328 } 329 330 intrGas := IntrinsicGas(tx.Data(), tx.To() == nil, true) 331 err = ValidPrivacyTx(stateDB, from.Bytes(), tx.Data(), tx.GasPrice(), intrGas, tx.Value(), gasLimit) 332 333 return err != nil 334 }) 335 336 var invalids types.Transactions 337 if l.strict && len(removed) > 0 { 338 lowest := uint64(math.MaxUint64) 339 for _, tx := range removed { 340 if nonce := tx.Nonce(); lowest > nonce { 341 lowest = nonce 342 } 343 } 344 invalids = l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > lowest }) 345 } 346 347 // Privacy transaction's sender is not real sender, just a hash info. 348 // So, no need to move invalid transactions to queue for later. 349 // Just remove all of invalid transactions. 350 return append(removed, invalids...) 351 } 352 353 // Cap places a hard limit on the number of items, returning all transactions 354 // exceeding that limit. 355 func (l *txList) Cap(threshold int) types.Transactions { 356 return l.txs.Cap(threshold) 357 } 358 359 // Remove deletes a transaction from the maintained list, returning whether the 360 // transaction was found, and also returning any transaction invalidated due to 361 // the deletion (strict mode only). 362 func (l *txList) Remove(tx *types.Transaction) (bool, types.Transactions) { 363 // Remove the transaction from the set 364 nonce := tx.Nonce() 365 if removed := l.txs.Remove(nonce); !removed { 366 return false, nil 367 } 368 // In strict mode, filter out non-executable transactions 369 if l.strict { 370 return true, l.txs.Filter(func(tx *types.Transaction) bool { return tx.Nonce() > nonce }) 371 } 372 return true, nil 373 } 374 375 // Ready retrieves a sequentially increasing list of transactions starting at the 376 // provided nonce that is ready for processing. The returned transactions will be 377 // removed from the list. 378 // 379 // Note, all transactions with nonces lower than start will also be returned to 380 // prevent getting into and invalid state. This is not something that should ever 381 // happen but better to be self correcting than failing! 382 func (l *txList) Ready(start uint64) types.Transactions { 383 return l.txs.Ready(start) 384 } 385 386 // Len returns the length of the transaction list. 387 func (l *txList) Len() int { 388 return l.txs.Len() 389 } 390 391 // Empty returns whether the list of transactions is empty or not. 392 func (l *txList) Empty() bool { 393 return l.Len() == 0 394 } 395 396 // Flatten creates a nonce-sorted slice of transactions based on the loosely 397 // sorted internal representation. The result of the sorting is cached in case 398 // it's requested again before any modifications are made to the contents. 399 func (l *txList) Flatten() types.Transactions { 400 return l.txs.Flatten() 401 } 402 403 // priceHeap is a heap.Interface implementation over transactions for retrieving 404 // price-sorted transactions to discard when the pool fills up. 405 type priceHeap []*types.Transaction 406 407 func (h priceHeap) Len() int { return len(h) } 408 func (h priceHeap) Less(i, j int) bool { return h[i].GasPrice().Cmp(h[j].GasPrice()) < 0 } 409 func (h priceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 410 411 func (h *priceHeap) Push(x interface{}) { 412 *h = append(*h, x.(*types.Transaction)) 413 } 414 415 func (h *priceHeap) Pop() interface{} { 416 old := *h 417 n := len(old) 418 x := old[n-1] 419 *h = old[0 : n-1] 420 return x 421 } 422 423 // txPricedList is a price-sorted heap to allow operating on transactions pool 424 // contents in a price-incrementing way. 425 type txPricedList struct { 426 all *map[common.Hash]*types.Transaction // Pointer to the map of all transactions 427 items *priceHeap // Heap of prices of all the stored transactions 428 stales int // Number of stale price points to (re-heap trigger) 429 } 430 431 // newTxPricedList creates a new price-sorted transaction heap. 432 func newTxPricedList(all *map[common.Hash]*types.Transaction) *txPricedList { 433 return &txPricedList{ 434 all: all, 435 items: new(priceHeap), 436 } 437 } 438 439 // Put inserts a new transaction into the heap. 440 func (l *txPricedList) Put(tx *types.Transaction) { 441 heap.Push(l.items, tx) 442 } 443 444 // Removed notifies the prices transaction list that an old transaction dropped 445 // from the pool. The list will just keep a counter of stale objects and update 446 // the heap if a large enough ratio of transactions go stale. 447 func (l *txPricedList) Removed() { 448 // Bump the stale counter, but exit if still too low (< 25%) 449 l.stales++ 450 if l.stales <= len(*l.items)/4 { 451 return 452 } 453 // Seems we've reached a critical number of stale transactions, reheap 454 reheap := make(priceHeap, 0, len(*l.all)) 455 456 l.stales, l.items = 0, &reheap 457 for _, tx := range *l.all { 458 *l.items = append(*l.items, tx) 459 } 460 heap.Init(l.items) 461 } 462 463 // Cap finds all the transactions below the given price threshold, drops them 464 // from the priced list and returs them for further removal from the entire pool. 465 func (l *txPricedList) Cap(threshold *big.Int, local *accountSet) types.Transactions { 466 drop := make(types.Transactions, 0, 128) // Remote underpriced transactions to drop 467 save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep 468 469 for len(*l.items) > 0 { 470 // Discard stale transactions if found during cleanup 471 tx := heap.Pop(l.items).(*types.Transaction) 472 if _, ok := (*l.all)[tx.Hash()]; !ok { 473 l.stales-- 474 continue 475 } 476 // Stop the discards if we've reached the threshold 477 if tx.GasPrice().Cmp(threshold) >= 0 { 478 save = append(save, tx) 479 break 480 } 481 // Non stale transaction found, discard unless local 482 if local.containsTx(tx) { 483 save = append(save, tx) 484 } else { 485 drop = append(drop, tx) 486 } 487 } 488 for _, tx := range save { 489 heap.Push(l.items, tx) 490 } 491 return drop 492 } 493 494 // Underpriced checks whether a transaction is cheaper than (or as cheap as) the 495 // lowest priced transaction currently being tracked. 496 func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) bool { 497 // Local transactions cannot be underpriced 498 if local.containsTx(tx) { 499 return false 500 } 501 // Discard stale price points if found at the heap start 502 for len(*l.items) > 0 { 503 head := []*types.Transaction(*l.items)[0] 504 if _, ok := (*l.all)[head.Hash()]; !ok { 505 l.stales-- 506 heap.Pop(l.items) 507 continue 508 } 509 break 510 } 511 // Check if the transaction is underpriced or not 512 if len(*l.items) == 0 { 513 log.Error("Pricing query for empty pool") // This cannot happen, print to catch programming errors 514 return false 515 } 516 cheapest := []*types.Transaction(*l.items)[0] 517 return cheapest.GasPrice().Cmp(tx.GasPrice()) >= 0 518 } 519 520 // Discard finds a number of most underpriced transactions, removes them from the 521 // priced list and returns them for further removal from the entire pool. 522 func (l *txPricedList) Discard(count int, local *accountSet) types.Transactions { 523 drop := make(types.Transactions, 0, count) // Remote underpriced transactions to drop 524 save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep 525 526 for len(*l.items) > 0 && count > 0 { 527 // Discard stale transactions if found during cleanup 528 tx := heap.Pop(l.items).(*types.Transaction) 529 if _, ok := (*l.all)[tx.Hash()]; !ok { 530 l.stales-- 531 continue 532 } 533 // Non stale transaction found, discard unless local 534 if local.containsTx(tx) { 535 save = append(save, tx) 536 } else { 537 drop = append(drop, tx) 538 count-- 539 } 540 } 541 for _, tx := range save { 542 heap.Push(l.items, tx) 543 } 544 return drop 545 }