github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/tx_pool.go (about) 1 package core 2 3 import ( 4 "errors" 5 "fmt" 6 "math" 7 "math/big" 8 "sort" 9 "sync" 10 "time" 11 12 "github.com/quickchainproject/quickchain/common" 13 "github.com/quickchainproject/quickchain/core/state" 14 "github.com/quickchainproject/quickchain/core/types" 15 "github.com/quickchainproject/quickchain/event" 16 "github.com/quickchainproject/quickchain/log" 17 "github.com/quickchainproject/quickchain/metrics" 18 "github.com/quickchainproject/quickchain/params" 19 "gopkg.in/karalabe/cookiejar.v2/collections/prque" 20 ) 21 22 const ( 23 // chainHeadChanSize is the size of channel listening to ChainHeadEvent. 24 chainHeadChanSize = 10 25 ) 26 27 var ( 28 // ErrInvalidSender is returned if the transaction contains an invalid signature. 29 ErrInvalidSender = errors.New("invalid sender") 30 31 // ErrNonceTooLow is returned if the nonce of a transaction is lower than the 32 // one present in the local chain. 33 ErrNonceTooLow = errors.New("nonce too low") 34 35 // ErrUnderpriced is returned if a transaction's gas price is below the minimum 36 // configured for the transaction pool. 37 ErrUnderpriced = errors.New("transaction underpriced") 38 39 // ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced 40 // with a different one without the required price bump. 41 ErrReplaceUnderpriced = errors.New("replacement transaction underpriced") 42 43 // ErrInsufficientFunds is returned if the total cost of executing a transaction 44 // is higher than the balance of the user's account. 45 ErrInsufficientFunds = errors.New("insufficient funds for gas * price + value") 46 47 // ErrIntrinsicGas is returned if the transaction is specified to use less gas 48 // than required to start the invocation. 49 ErrIntrinsicGas = errors.New("intrinsic gas too low") 50 51 // ErrGasLimit is returned if a transaction's requested gas limit exceeds the 52 // maximum allowance of the current block. 53 ErrGasLimit = errors.New("exceeds block gas limit") 54 55 // ErrNegativeValue is a sanity error to ensure noone is able to specify a 56 // transaction with a negative value. 57 ErrNegativeValue = errors.New("negative value") 58 59 // ErrOversizedData is returned if the input data of a transaction is greater 60 // than some meaningful limit a user might use. This is not a consensus error 61 // making the transaction invalid, rather a DOS protection. 62 ErrOversizedData = errors.New("oversized data") 63 ) 64 65 var ( 66 evictionInterval = time.Minute // Time interval to check for evictable transactions 67 statsReportInterval = 8 * time.Second // Time interval to report transaction pool stats 68 ) 69 70 var ( 71 // Metrics for the pending pool 72 pendingDiscardCounter = metrics.NewRegisteredCounter("txpool/pending/discard", nil) 73 pendingReplaceCounter = metrics.NewRegisteredCounter("txpool/pending/replace", nil) 74 pendingRateLimitCounter = metrics.NewRegisteredCounter("txpool/pending/ratelimit", nil) // Dropped due to rate limiting 75 pendingNofundsCounter = metrics.NewRegisteredCounter("txpool/pending/nofunds", nil) // Dropped due to out-of-funds 76 77 // Metrics for the queued pool 78 queuedDiscardCounter = metrics.NewRegisteredCounter("txpool/queued/discard", nil) 79 queuedReplaceCounter = metrics.NewRegisteredCounter("txpool/queued/replace", nil) 80 queuedRateLimitCounter = metrics.NewRegisteredCounter("txpool/queued/ratelimit", nil) // Dropped due to rate limiting 81 queuedNofundsCounter = metrics.NewRegisteredCounter("txpool/queued/nofunds", nil) // Dropped due to out-of-funds 82 83 // General tx metrics 84 invalidTxCounter = metrics.NewRegisteredCounter("txpool/invalid", nil) 85 underpricedTxCounter = metrics.NewRegisteredCounter("txpool/underpriced", nil) 86 ) 87 88 // TxStatus is the current status of a transaction as seen by the pool. 89 type TxStatus uint 90 91 const ( 92 TxStatusUnknown TxStatus = iota 93 TxStatusQueued 94 TxStatusPending 95 TxStatusIncluded 96 ) 97 98 // blockChain provides the state of blockchain and current gas limit to do 99 // some pre checks in tx pool and event subscribers. 100 type blockChain interface { 101 CurrentBlock() *types.Block 102 GetBlock(hash common.Hash, number uint64) *types.Block 103 StateAt(root common.Hash) (*state.StateDB, error) 104 105 SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription 106 } 107 108 // TxPoolConfig are the configuration parameters of the transaction pool. 109 type TxPoolConfig struct { 110 NoLocals bool // Whether local transaction handling should be disabled 111 Journal string // Journal of local transactions to survive node restarts 112 Rejournal time.Duration // Time interval to regenerate the local transaction journal 113 114 PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool 115 PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce) 116 117 AccountSlots uint64 // Minimum number of executable transaction slots guaranteed per account 118 GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts 119 AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account 120 GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts 121 122 BatchSyncSize uint64 // Minimum number of tx pool transactions sync size 123 124 Lifetime time.Duration // Maximum amount of time non-executable transaction are queued 125 } 126 127 // DefaultTxPoolConfig contains the default configurations for the transaction 128 // pool. 129 var DefaultTxPoolConfig = TxPoolConfig{ 130 Journal: "transactions.rlp", 131 Rejournal: time.Hour, 132 133 PriceLimit: 1, 134 PriceBump: 10, 135 136 AccountSlots: 16, 137 GlobalSlots: 8192, 138 AccountQueue: 64, 139 GlobalQueue: 1024, 140 141 BatchSyncSize: 8, 142 143 Lifetime: 3 * time.Hour, 144 } 145 146 // sanitize checks the provided user configurations and changes anything that's 147 // unreasonable or unworkable. 148 func (config *TxPoolConfig) sanitize() TxPoolConfig { 149 conf := *config 150 if conf.Rejournal < time.Second { 151 log.Warn("Sanitizing invalid txpool journal time", "provided", conf.Rejournal, "updated", time.Second) 152 conf.Rejournal = time.Second 153 } 154 if conf.PriceLimit < 1 { 155 log.Warn("Sanitizing invalid txpool price limit", "provided", conf.PriceLimit, "updated", DefaultTxPoolConfig.PriceLimit) 156 conf.PriceLimit = DefaultTxPoolConfig.PriceLimit 157 } 158 if conf.PriceBump < 1 { 159 log.Warn("Sanitizing invalid txpool price bump", "provided", conf.PriceBump, "updated", DefaultTxPoolConfig.PriceBump) 160 conf.PriceBump = DefaultTxPoolConfig.PriceBump 161 } 162 return conf 163 } 164 165 // TxPool contains all currently known transactions. Transactions 166 // enter the pool when they are received from the network or submitted 167 // locally. They exit the pool when they are included in the blockchain. 168 // 169 // The pool separates processable transactions (which can be applied to the 170 // current state) and future transactions. Transactions move between those 171 // two states over time as they are received and processed. 172 type TxPool struct { 173 config TxPoolConfig 174 chainconfig *params.ChainConfig 175 chain blockChain 176 gasPrice *big.Int 177 txFeed event.Feed 178 scope event.SubscriptionScope 179 chainHeadCh chan ChainHeadEvent 180 chainHeadSub event.Subscription 181 signer types.Signer 182 mu sync.RWMutex 183 184 currentState *state.StateDB // Current state in the blockchain head 185 pendingState *state.ManagedState // Pending state tracking virtual nonces 186 currentMaxGas uint64 // Current gas limit for transaction caps 187 188 locals *accountSet // Set of local transaction to exempt from eviction rules 189 journal *txJournal // Journal of local transaction to back up to disk 190 191 pending map[common.Address]*txList // All currently processable transactions 192 queue map[common.Address]*txList // Queued but non-processable transactions 193 beats map[common.Address]time.Time // Last heartbeat from each known account 194 all map[common.Hash]*types.Transaction // All transactions to allow lookups 195 priced *txPricedList // All transactions sorted by price 196 197 wg sync.WaitGroup // for shutdown sync 198 199 homestead bool 200 } 201 202 // NewTxPool creates a new transaction pool to gather, sort and filter inbound 203 // transactions from the network. 204 func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain blockChain) *TxPool { 205 // Sanitize the input to ensure no vulnerable gas prices are set 206 config = (&config).sanitize() 207 208 // Create the transaction pool with its initial settings 209 pool := &TxPool{ 210 config: config, 211 chainconfig: chainconfig, 212 chain: chain, 213 signer: types.NewEIP155Signer(chainconfig.ChainId), 214 pending: make(map[common.Address]*txList), 215 queue: make(map[common.Address]*txList), 216 beats: make(map[common.Address]time.Time), 217 all: make(map[common.Hash]*types.Transaction), 218 chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize), 219 gasPrice: new(big.Int).SetUint64(config.PriceLimit), 220 } 221 pool.locals = newAccountSet(pool.signer) 222 pool.priced = newTxPricedList(&pool.all) 223 pool.reset(nil, chain.CurrentBlock().Header()) 224 225 // If local transactions and journaling is enabled, load from disk 226 if !config.NoLocals && config.Journal != "" { 227 pool.journal = newTxJournal(config.Journal) 228 229 if err := pool.journal.load(pool.AddLocal); err != nil { 230 log.Warn("Failed to load transaction journal", "err", err) 231 } 232 if err := pool.journal.rotate(pool.local()); err != nil { 233 log.Warn("Failed to rotate transaction journal", "err", err) 234 } 235 } 236 // Subscribe events from blockchain 237 pool.chainHeadSub = pool.chain.SubscribeChainHeadEvent(pool.chainHeadCh) 238 239 // Start the event loop and return 240 pool.wg.Add(1) 241 go pool.loop() 242 243 return pool 244 } 245 246 // loop is the transaction pool's main event loop, waiting for and reacting to 247 // outside blockchain events as well as for various reporting and transaction 248 // eviction events. 249 func (pool *TxPool) loop() { 250 defer pool.wg.Done() 251 252 // Start the stats reporting and transaction eviction tickers 253 var prevPending, prevQueued, prevStales int 254 255 report := time.NewTicker(statsReportInterval) 256 defer report.Stop() 257 258 evict := time.NewTicker(evictionInterval) 259 defer evict.Stop() 260 261 journal := time.NewTicker(pool.config.Rejournal) 262 defer journal.Stop() 263 264 // Track the previous head headers for transaction reorgs 265 head := pool.chain.CurrentBlock() 266 267 // Keep waiting for and reacting to the various events 268 for { 269 select { 270 // Handle ChainHeadEvent 271 case ev := <-pool.chainHeadCh: 272 if ev.Block != nil { 273 pool.mu.Lock() 274 if pool.chainconfig.IsHomestead(ev.Block.Number()) { 275 pool.homestead = true 276 } 277 pool.reset(head.Header(), ev.Block.Header()) 278 head = ev.Block 279 280 pool.mu.Unlock() 281 } 282 // Be unsubscribed due to system stopped 283 case <-pool.chainHeadSub.Err(): 284 return 285 286 // Handle stats reporting ticks 287 case <-report.C: 288 pool.mu.RLock() 289 pending, queued := pool.stats() 290 stales := pool.priced.stales 291 pool.mu.RUnlock() 292 293 if pending != prevPending || queued != prevQueued || stales != prevStales { 294 log.Debug("Transaction pool status report", "executable", pending, "queued", queued, "stales", stales) 295 prevPending, prevQueued, prevStales = pending, queued, stales 296 } 297 298 // Handle inactive account transaction eviction 299 case <-evict.C: 300 pool.mu.Lock() 301 for addr := range pool.queue { 302 // Skip local transactions from the eviction mechanism 303 if pool.locals.contains(addr) { 304 continue 305 } 306 // Any non-locals old enough should be removed 307 if time.Since(pool.beats[addr]) > pool.config.Lifetime { 308 for _, tx := range pool.queue[addr].Flatten() { 309 pool.removeTx(tx.Hash(), true) 310 } 311 } 312 } 313 pool.mu.Unlock() 314 315 // Handle local transaction journal rotation 316 case <-journal.C: 317 if pool.journal != nil { 318 pool.mu.Lock() 319 if err := pool.journal.rotate(pool.local()); err != nil { 320 log.Warn("Failed to rotate local tx journal", "err", err) 321 } 322 pool.mu.Unlock() 323 } 324 } 325 } 326 } 327 328 // lockedReset is a wrapper around reset to allow calling it in a thread safe 329 // manner. This method is only ever used in the tester! 330 func (pool *TxPool) lockedReset(oldHead, newHead *types.Header) { 331 pool.mu.Lock() 332 defer pool.mu.Unlock() 333 334 pool.reset(oldHead, newHead) 335 } 336 337 // reset retrieves the current state of the blockchain and ensures the content 338 // of the transaction pool is valid with regard to the chain state. 339 func (pool *TxPool) reset(oldHead, newHead *types.Header) { 340 // If we're reorging an old state, reinject all dropped transactions 341 var reinject types.Transactions 342 343 if oldHead != nil && oldHead.Hash() != newHead.ParentHash { 344 // If the reorg is too deep, avoid doing it (will happen during fast sync) 345 oldNum := oldHead.Number.Uint64() 346 newNum := newHead.Number.Uint64() 347 348 if depth := uint64(math.Abs(float64(oldNum) - float64(newNum))); depth > 64 { 349 log.Debug("Skipping deep transaction reorg", "depth", depth) 350 } else { 351 // Reorg seems shallow enough to pull in all transactions into memory 352 var discarded, included types.Transactions 353 354 var ( 355 rem = pool.chain.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) 356 add = pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64()) 357 ) 358 for rem.NumberU64() > add.NumberU64() { 359 discarded = append(discarded, rem.Transactions()...) 360 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 361 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 362 return 363 } 364 } 365 for add.NumberU64() > rem.NumberU64() { 366 included = append(included, add.Transactions()...) 367 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 368 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 369 return 370 } 371 } 372 for rem.Hash() != add.Hash() { 373 discarded = append(discarded, rem.Transactions()...) 374 if rem = pool.chain.GetBlock(rem.ParentHash(), rem.NumberU64()-1); rem == nil { 375 log.Error("Unrooted old chain seen by tx pool", "block", oldHead.Number, "hash", oldHead.Hash()) 376 return 377 } 378 included = append(included, add.Transactions()...) 379 if add = pool.chain.GetBlock(add.ParentHash(), add.NumberU64()-1); add == nil { 380 log.Error("Unrooted new chain seen by tx pool", "block", newHead.Number, "hash", newHead.Hash()) 381 return 382 } 383 } 384 reinject = types.TxDifference(discarded, included) 385 } 386 } 387 // Initialize the internal state to the current head 388 if newHead == nil { 389 newHead = pool.chain.CurrentBlock().Header() // Special case during testing 390 } 391 statedb, err := pool.chain.StateAt(newHead.Root) 392 if err != nil { 393 log.Error("Failed to reset txpool state", "err", err) 394 return 395 } 396 pool.currentState = statedb 397 pool.pendingState = state.ManageState(statedb) 398 pool.currentMaxGas = newHead.GasLimit 399 400 // Inject any transactions discarded due to reorgs 401 log.Debug("Reinjecting stale transactions", "count", len(reinject)) 402 pool.addTxsLocked(reinject, false) 403 404 // validate the pool of pending transactions, this will remove 405 // any transactions that have been included in the block or 406 // have been invalidated because of another transaction (e.g. 407 // higher gas price) 408 pool.demoteUnexecutables() 409 410 // Update all accounts to the latest known pending nonce 411 for addr, list := range pool.pending { 412 txs := list.Flatten() // Heavy but will be cached and is needed by the miner anyway 413 pool.pendingState.SetNonce(addr, txs[len(txs)-1].Nonce()+1) 414 } 415 // Check the queue and move transactions over to the pending if possible 416 // or remove those that have become invalid 417 pool.promoteExecutables(nil) 418 } 419 420 // Stop terminates the transaction pool. 421 func (pool *TxPool) Stop() { 422 // Unsubscribe all subscriptions registered from txpool 423 pool.scope.Close() 424 425 // Unsubscribe subscriptions registered from blockchain 426 pool.chainHeadSub.Unsubscribe() 427 pool.wg.Wait() 428 429 if pool.journal != nil { 430 pool.journal.close() 431 } 432 log.Info("Transaction pool stopped") 433 } 434 435 // SubscribeTxPreEvent registers a subscription of TxPreEvent and 436 // starts sending event to the given channel. 437 func (pool *TxPool) SubscribeTxPreEvent(ch chan<- TxPreEvent) event.Subscription { 438 return pool.scope.Track(pool.txFeed.Subscribe(ch)) 439 } 440 441 // GasPrice returns the current gas price enforced by the transaction pool. 442 func (pool *TxPool) GasPrice() *big.Int { 443 pool.mu.RLock() 444 defer pool.mu.RUnlock() 445 446 return new(big.Int).Set(pool.gasPrice) 447 } 448 449 // SetGasPrice updates the minimum price required by the transaction pool for a 450 // new transaction, and drops all transactions below this threshold. 451 func (pool *TxPool) SetGasPrice(price *big.Int) { 452 pool.mu.Lock() 453 defer pool.mu.Unlock() 454 455 pool.gasPrice = price 456 for _, tx := range pool.priced.Cap(price, pool.locals) { 457 pool.removeTx(tx.Hash(), false) 458 } 459 log.Info("Transaction pool price threshold updated", "price", price) 460 } 461 462 // State returns the virtual managed state of the transaction pool. 463 func (pool *TxPool) State() *state.ManagedState { 464 pool.mu.RLock() 465 defer pool.mu.RUnlock() 466 467 return pool.pendingState 468 } 469 470 // Stats retrieves the current pool stats, namely the number of pending and the 471 // number of queued (non-executable) transactions. 472 func (pool *TxPool) Stats() (int, int) { 473 pool.mu.RLock() 474 defer pool.mu.RUnlock() 475 476 return pool.stats() 477 } 478 479 // stats retrieves the current pool stats, namely the number of pending and the 480 // number of queued (non-executable) transactions. 481 func (pool *TxPool) stats() (int, int) { 482 pending := 0 483 for _, list := range pool.pending { 484 pending += list.Len() 485 } 486 queued := 0 487 for _, list := range pool.queue { 488 queued += list.Len() 489 } 490 return pending, queued 491 } 492 493 // Content retrieves the data content of the transaction pool, returning all the 494 // pending as well as queued transactions, grouped by account and sorted by nonce. 495 func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 496 pool.mu.Lock() 497 defer pool.mu.Unlock() 498 499 pending := make(map[common.Address]types.Transactions) 500 for addr, list := range pool.pending { 501 pending[addr] = list.Flatten() 502 } 503 queued := make(map[common.Address]types.Transactions) 504 for addr, list := range pool.queue { 505 queued[addr] = list.Flatten() 506 } 507 return pending, queued 508 } 509 510 // Pending retrieves all currently processable transactions, groupped by origin 511 // account and sorted by nonce. The returned transaction set is a copy and can be 512 // freely modified by calling code. 513 func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) { 514 pool.mu.Lock() 515 defer pool.mu.Unlock() 516 517 pending := make(map[common.Address]types.Transactions) 518 for addr, list := range pool.pending { 519 pending[addr] = list.Flatten() 520 } 521 return pending, nil 522 } 523 524 func (pool *TxPool) RemoveTx(hash common.Hash, outofbound bool) { 525 pool.mu.Lock() 526 defer pool.mu.Unlock() 527 528 pool.removeTx(hash, true) 529 } 530 531 // local retrieves all currently known local transactions, groupped by origin 532 // account and sorted by nonce. The returned transaction set is a copy and can be 533 // freely modified by calling code. 534 func (pool *TxPool) local() map[common.Address]types.Transactions { 535 txs := make(map[common.Address]types.Transactions) 536 for addr := range pool.locals.accounts { 537 if pending := pool.pending[addr]; pending != nil { 538 txs[addr] = append(txs[addr], pending.Flatten()...) 539 } 540 if queued := pool.queue[addr]; queued != nil { 541 txs[addr] = append(txs[addr], queued.Flatten()...) 542 } 543 } 544 return txs 545 } 546 547 // validateTx checks whether a transaction is valid according to the consensus 548 // rules and adheres to some heuristic limits of the local node (price and size). 549 func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { 550 // Heuristic limit, reject transactions over 32KB to prevent DOS attacks 551 if tx.Size() > 32*1024 { 552 return ErrOversizedData 553 } 554 // Transactions can't be negative. This may never happen using RLP decoded 555 // transactions but may occur if you create a transaction using the RPC. 556 if tx.Value().Sign() < 0 { 557 return ErrNegativeValue 558 } 559 // Ensure the transaction doesn't exceed the current block limit gas. 560 if pool.currentMaxGas < tx.Gas() { 561 return ErrGasLimit 562 } 563 // Make sure the transaction is signed properly 564 from, err := types.Sender(pool.signer, tx) 565 if err != nil { 566 return ErrInvalidSender 567 } 568 // Drop non-local transactions under our own minimal accepted gas price 569 local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network 570 if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { 571 return ErrUnderpriced 572 } 573 // Ensure the transaction adheres to nonce ordering 574 if pool.currentState.GetNonce(from) > tx.Nonce() { 575 return ErrNonceTooLow 576 } 577 // Transactor should have enough funds to cover the costs 578 // cost == V + GP * GL 579 if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { 580 return ErrInsufficientFunds 581 } 582 intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead) 583 if err != nil { 584 return err 585 } 586 if tx.Gas() < intrGas { 587 return ErrIntrinsicGas 588 } 589 return nil 590 } 591 592 // add validates a transaction and inserts it into the non-executable queue for 593 // later pending promotion and execution. If the transaction is a replacement for 594 // an already pending or queued one, it overwrites the previous and returns this 595 // so outer code doesn't uselessly call promote. 596 // 597 // If a newly added transaction is marked as local, its sending account will be 598 // whitelisted, preventing any associated transaction from being dropped out of 599 // the pool due to pricing constraints. 600 func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { 601 // If the transaction is already known, discard it 602 hash := tx.Hash() 603 if pool.all[hash] != nil { 604 log.Trace("Discarding already known transaction", "hash", hash) 605 return false, fmt.Errorf("known transaction: %x", hash) 606 } 607 // If the transaction fails basic validation, discard it 608 if err := pool.validateTx(tx, local); err != nil { 609 log.Trace("Discarding invalid transaction", "hash", hash, "err", err) 610 invalidTxCounter.Inc(1) 611 return false, err 612 } 613 // If the transaction pool is full, discard underpriced transactions 614 if uint64(len(pool.all)) >= pool.config.GlobalSlots+pool.config.GlobalQueue { 615 // If the new transaction is underpriced, don't accept it 616 if !local && pool.priced.Underpriced(tx, pool.locals) { 617 log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice()) 618 underpricedTxCounter.Inc(1) 619 return false, ErrUnderpriced 620 } 621 // New transaction is better than our worse ones, make room for it 622 drop := pool.priced.Discard(len(pool.all)-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals) 623 for _, tx := range drop { 624 log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "price", tx.GasPrice()) 625 underpricedTxCounter.Inc(1) 626 pool.removeTx(tx.Hash(), false) 627 } 628 } 629 // If the transaction is replacing an already pending one, do directly 630 from, _ := types.Sender(pool.signer, tx) // already validated 631 if list := pool.pending[from]; list != nil && list.Overlaps(tx) { 632 // Nonce already pending, check if required price bump is met 633 inserted, old := list.Add(tx, pool.config.PriceBump) 634 if !inserted { 635 pendingDiscardCounter.Inc(1) 636 return false, ErrReplaceUnderpriced 637 } 638 // New transaction is better, replace old one 639 if old != nil { 640 delete(pool.all, old.Hash()) 641 pool.priced.Removed() 642 pendingReplaceCounter.Inc(1) 643 } 644 pool.all[tx.Hash()] = tx 645 pool.priced.Put(tx) 646 pool.journalTx(from, tx) 647 648 log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To()) 649 650 // We've directly injected a replacement transaction, notify subsystems 651 go pool.txFeed.Send(TxPreEvent{tx}) 652 653 return old != nil, nil 654 } 655 // New transaction isn't replacing a pending one, push into queue 656 replace, err := pool.enqueueTx(hash, tx) 657 if err != nil { 658 return false, err 659 } 660 // Mark local addresses and journal local transactions 661 if local { 662 pool.locals.add(from) 663 } 664 pool.journalTx(from, tx) 665 666 log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To()) 667 return replace, nil 668 } 669 670 // enqueueTx inserts a new transaction into the non-executable transaction queue. 671 // 672 // Note, this method assumes the pool lock is held! 673 func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) (bool, error) { 674 // Try to insert the transaction into the future queue 675 from, _ := types.Sender(pool.signer, tx) // already validated 676 if pool.queue[from] == nil { 677 pool.queue[from] = newTxList(false) 678 } 679 inserted, old := pool.queue[from].Add(tx, pool.config.PriceBump) 680 if !inserted { 681 // An older transaction was better, discard this 682 queuedDiscardCounter.Inc(1) 683 return false, ErrReplaceUnderpriced 684 } 685 // Discard any previous transaction and mark this 686 if old != nil { 687 delete(pool.all, old.Hash()) 688 pool.priced.Removed() 689 queuedReplaceCounter.Inc(1) 690 } 691 if pool.all[hash] == nil { 692 pool.all[hash] = tx 693 pool.priced.Put(tx) 694 } 695 return old != nil, nil 696 } 697 698 // journalTx adds the specified transaction to the local disk journal if it is 699 // deemed to have been sent from a local account. 700 func (pool *TxPool) journalTx(from common.Address, tx *types.Transaction) { 701 // Only journal if it's enabled and the transaction is local 702 if pool.journal == nil || !pool.locals.contains(from) { 703 return 704 } 705 if err := pool.journal.insert(tx); err != nil { 706 log.Warn("Failed to journal local transaction", "err", err) 707 } 708 } 709 710 // promoteTx adds a transaction to the pending (processable) list of transactions. 711 // 712 // Note, this method assumes the pool lock is held! 713 func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) { 714 // Try to insert the transaction into the pending queue 715 if pool.pending[addr] == nil { 716 pool.pending[addr] = newTxList(true) 717 } 718 list := pool.pending[addr] 719 720 inserted, old := list.Add(tx, pool.config.PriceBump) 721 if !inserted { 722 // An older transaction was better, discard this 723 delete(pool.all, hash) 724 pool.priced.Removed() 725 726 pendingDiscardCounter.Inc(1) 727 return 728 } 729 // Otherwise discard any previous transaction and mark this 730 if old != nil { 731 delete(pool.all, old.Hash()) 732 pool.priced.Removed() 733 734 pendingReplaceCounter.Inc(1) 735 } 736 // Failsafe to work around direct pending inserts (tests) 737 if pool.all[hash] == nil { 738 pool.all[hash] = tx 739 pool.priced.Put(tx) 740 } 741 // Set the potentially new pending nonce and notify any subsystems of the new tx 742 pool.beats[addr] = time.Now() 743 pool.pendingState.SetNonce(addr, tx.Nonce()+1) 744 745 go pool.txFeed.Send(TxPreEvent{tx}) 746 } 747 748 // AddLocal enqueues a single transaction into the pool if it is valid, marking 749 // the sender as a local one in the mean time, ensuring it goes around the local 750 // pricing constraints. 751 func (pool *TxPool) AddLocal(tx *types.Transaction) error { 752 return pool.addTx(tx, !pool.config.NoLocals) 753 } 754 755 // AddRemote enqueues a single transaction into the pool if it is valid. If the 756 // sender is not among the locally tracked ones, full pricing constraints will 757 // apply. 758 func (pool *TxPool) AddRemote(tx *types.Transaction) error { 759 return pool.addTx(tx, false) 760 } 761 762 // AddLocals enqueues a batch of transactions into the pool if they are valid, 763 // marking the senders as a local ones in the mean time, ensuring they go around 764 // the local pricing constraints. 765 func (pool *TxPool) AddLocals(txs []*types.Transaction) []error { 766 return pool.addTxs(txs, !pool.config.NoLocals) 767 } 768 769 // AddRemotes enqueues a batch of transactions into the pool if they are valid. 770 // If the senders are not among the locally tracked ones, full pricing constraints 771 // will apply. 772 func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error { 773 return pool.addTxs(txs, false) 774 } 775 776 // addTx enqueues a single transaction into the pool if it is valid. 777 func (pool *TxPool) addTx(tx *types.Transaction, local bool) error { 778 pool.mu.Lock() 779 defer pool.mu.Unlock() 780 781 // Try to inject the transaction and update any state 782 replace, err := pool.add(tx, local) 783 if err != nil { 784 return err 785 } 786 // If we added a new transaction, run promotion checks and return 787 if !replace { 788 from, _ := types.Sender(pool.signer, tx) // already validated 789 pool.promoteExecutables([]common.Address{from}) 790 } 791 return nil 792 } 793 794 // addTxs attempts to queue a batch of transactions if they are valid. 795 func (pool *TxPool) addTxs(txs []*types.Transaction, local bool) []error { 796 pool.mu.Lock() 797 defer pool.mu.Unlock() 798 799 return pool.addTxsLocked(txs, local) 800 } 801 802 // addTxsLocked attempts to queue a batch of transactions if they are valid, 803 // whilst assuming the transaction pool lock is already held. 804 func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) []error { 805 // Add the batch of transaction, tracking the accepted ones 806 dirty := make(map[common.Address]struct{}) 807 errs := make([]error, len(txs)) 808 809 for i, tx := range txs { 810 var replace bool 811 if replace, errs[i] = pool.add(tx, local); errs[i] == nil { 812 if !replace { 813 from, _ := types.Sender(pool.signer, tx) // already validated 814 dirty[from] = struct{}{} 815 } 816 } 817 } 818 // Only reprocess the internal state if something was actually added 819 if len(dirty) > 0 { 820 addrs := make([]common.Address, 0, len(dirty)) 821 for addr := range dirty { 822 addrs = append(addrs, addr) 823 } 824 pool.promoteExecutables(addrs) 825 } 826 return errs 827 } 828 829 // Status returns the status (unknown/pending/queued) of a batch of transactions 830 // identified by their hashes. 831 func (pool *TxPool) Status(hashes []common.Hash) []TxStatus { 832 pool.mu.RLock() 833 defer pool.mu.RUnlock() 834 835 status := make([]TxStatus, len(hashes)) 836 for i, hash := range hashes { 837 if tx := pool.all[hash]; tx != nil { 838 from, _ := types.Sender(pool.signer, tx) // already validated 839 if pool.pending[from] != nil && pool.pending[from].txs.items[tx.Nonce()] != nil { 840 status[i] = TxStatusPending 841 } else { 842 status[i] = TxStatusQueued 843 } 844 } 845 } 846 return status 847 } 848 849 // Get returns a transaction if it is contained in the pool 850 // and nil otherwise. 851 func (pool *TxPool) Get(hash common.Hash) *types.Transaction { 852 pool.mu.RLock() 853 defer pool.mu.RUnlock() 854 855 return pool.all[hash] 856 } 857 858 // removeTx removes a single transaction from the queue, moving all subsequent 859 // transactions back to the future queue. 860 func (pool *TxPool) removeTx(hash common.Hash, outofbound bool) { 861 // Fetch the transaction we wish to delete 862 tx, ok := pool.all[hash] 863 if !ok { 864 return 865 } 866 addr, _ := types.Sender(pool.signer, tx) // already validated during insertion 867 868 // Remove it from the list of known transactions 869 delete(pool.all, hash) 870 if outofbound { 871 pool.priced.Removed() 872 } 873 // Remove the transaction from the pending lists and reset the account nonce 874 if pending := pool.pending[addr]; pending != nil { 875 if removed, invalids := pending.Remove(tx); removed { 876 // If no more pending transactions are left, remove the list 877 if pending.Empty() { 878 delete(pool.pending, addr) 879 delete(pool.beats, addr) 880 } 881 // Postpone any invalidated transactions 882 for _, tx := range invalids { 883 pool.enqueueTx(tx.Hash(), tx) 884 } 885 // Update the account nonce if needed 886 if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { 887 pool.pendingState.SetNonce(addr, nonce) 888 } 889 return 890 } 891 } 892 // Transaction is in the future queue 893 if future := pool.queue[addr]; future != nil { 894 future.Remove(tx) 895 if future.Empty() { 896 delete(pool.queue, addr) 897 } 898 } 899 } 900 901 // promoteExecutables moves transactions that have become processable from the 902 // future queue to the set of pending transactions. During this process, all 903 // invalidated transactions (low nonce, low balance) are deleted. 904 func (pool *TxPool) promoteExecutables(accounts []common.Address) { 905 // Gather all the accounts potentially needing updates 906 if accounts == nil { 907 accounts = make([]common.Address, 0, len(pool.queue)) 908 for addr := range pool.queue { 909 accounts = append(accounts, addr) 910 } 911 } 912 // Iterate over all accounts and promote any executable transactions 913 for _, addr := range accounts { 914 list := pool.queue[addr] 915 if list == nil { 916 continue // Just in case someone calls with a non existing account 917 } 918 // Drop all transactions that are deemed too old (low nonce) 919 for _, tx := range list.Forward(pool.currentState.GetNonce(addr)) { 920 hash := tx.Hash() 921 log.Trace("Removed old queued transaction", "hash", hash) 922 delete(pool.all, hash) 923 pool.priced.Removed() 924 } 925 // Drop all transactions that are too costly (low balance or out of gas) 926 drops, _ := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) 927 for _, tx := range drops { 928 hash := tx.Hash() 929 log.Trace("Removed unpayable queued transaction", "hash", hash) 930 delete(pool.all, hash) 931 pool.priced.Removed() 932 queuedNofundsCounter.Inc(1) 933 } 934 // Gather all executable transactions and promote them 935 for _, tx := range list.Ready(pool.pendingState.GetNonce(addr)) { 936 hash := tx.Hash() 937 log.Trace("Promoting queued transaction", "hash", hash) 938 pool.promoteTx(addr, hash, tx) 939 } 940 // Drop all transactions over the allowed limit 941 if !pool.locals.contains(addr) { 942 for _, tx := range list.Cap(int(pool.config.AccountQueue)) { 943 hash := tx.Hash() 944 delete(pool.all, hash) 945 pool.priced.Removed() 946 queuedRateLimitCounter.Inc(1) 947 log.Trace("Removed cap-exceeding queued transaction", "hash", hash) 948 } 949 } 950 // Delete the entire queue entry if it became empty. 951 if list.Empty() { 952 delete(pool.queue, addr) 953 } 954 } 955 // If the pending limit is overflown, start equalizing allowances 956 pending := uint64(0) 957 for _, list := range pool.pending { 958 pending += uint64(list.Len()) 959 } 960 if pending > pool.config.GlobalSlots { 961 pendingBeforeCap := pending 962 // Assemble a spam order to penalize large transactors first 963 spammers := prque.New() 964 for addr, list := range pool.pending { 965 // Only evict transactions from high rollers 966 if !pool.locals.contains(addr) && uint64(list.Len()) > pool.config.AccountSlots { 967 spammers.Push(addr, float32(list.Len())) 968 } 969 } 970 // Gradually drop transactions from offenders 971 offenders := []common.Address{} 972 for pending > pool.config.GlobalSlots && !spammers.Empty() { 973 // Retrieve the next offender if not local address 974 offender, _ := spammers.Pop() 975 offenders = append(offenders, offender.(common.Address)) 976 977 // Equalize balances until all the same or below threshold 978 if len(offenders) > 1 { 979 // Calculate the equalization threshold for all current offenders 980 threshold := pool.pending[offender.(common.Address)].Len() 981 982 // Iteratively reduce all offenders until below limit or threshold reached 983 for pending > pool.config.GlobalSlots && pool.pending[offenders[len(offenders)-2]].Len() > threshold { 984 for i := 0; i < len(offenders)-1; i++ { 985 list := pool.pending[offenders[i]] 986 for _, tx := range list.Cap(list.Len() - 1) { 987 // Drop the transaction from the global pools too 988 hash := tx.Hash() 989 delete(pool.all, hash) 990 pool.priced.Removed() 991 992 // Update the account nonce to the dropped transaction 993 if nonce := tx.Nonce(); pool.pendingState.GetNonce(offenders[i]) > nonce { 994 pool.pendingState.SetNonce(offenders[i], nonce) 995 } 996 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 997 } 998 pending-- 999 } 1000 } 1001 } 1002 } 1003 // If still above threshold, reduce to limit or min allowance 1004 if pending > pool.config.GlobalSlots && len(offenders) > 0 { 1005 for pending > pool.config.GlobalSlots && uint64(pool.pending[offenders[len(offenders)-1]].Len()) > pool.config.AccountSlots { 1006 for _, addr := range offenders { 1007 list := pool.pending[addr] 1008 for _, tx := range list.Cap(list.Len() - 1) { 1009 // Drop the transaction from the global pools too 1010 hash := tx.Hash() 1011 delete(pool.all, hash) 1012 pool.priced.Removed() 1013 1014 // Update the account nonce to the dropped transaction 1015 if nonce := tx.Nonce(); pool.pendingState.GetNonce(addr) > nonce { 1016 pool.pendingState.SetNonce(addr, nonce) 1017 } 1018 log.Trace("Removed fairness-exceeding pending transaction", "hash", hash) 1019 } 1020 pending-- 1021 } 1022 } 1023 } 1024 pendingRateLimitCounter.Inc(int64(pendingBeforeCap - pending)) 1025 } 1026 // If we've queued more transactions than the hard limit, drop oldest ones 1027 queued := uint64(0) 1028 for _, list := range pool.queue { 1029 queued += uint64(list.Len()) 1030 } 1031 if queued > pool.config.GlobalQueue { 1032 // Sort all accounts with queued transactions by heartbeat 1033 addresses := make(addresssByHeartbeat, 0, len(pool.queue)) 1034 for addr := range pool.queue { 1035 if !pool.locals.contains(addr) { // don't drop locals 1036 addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) 1037 } 1038 } 1039 sort.Sort(addresses) 1040 1041 // Drop transactions until the total is below the limit or only locals remain 1042 for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { 1043 addr := addresses[len(addresses)-1] 1044 list := pool.queue[addr.address] 1045 1046 addresses = addresses[:len(addresses)-1] 1047 1048 // Drop all transactions if they are less than the overflow 1049 if size := uint64(list.Len()); size <= drop { 1050 for _, tx := range list.Flatten() { 1051 pool.removeTx(tx.Hash(), true) 1052 } 1053 drop -= size 1054 queuedRateLimitCounter.Inc(int64(size)) 1055 continue 1056 } 1057 // Otherwise drop only last few transactions 1058 txs := list.Flatten() 1059 for i := len(txs) - 1; i >= 0 && drop > 0; i-- { 1060 pool.removeTx(txs[i].Hash(), true) 1061 drop-- 1062 queuedRateLimitCounter.Inc(1) 1063 } 1064 } 1065 } 1066 } 1067 1068 // demoteUnexecutables removes invalid and processed transactions from the pools 1069 // executable/pending queue and any subsequent transactions that become unexecutable 1070 // are moved back into the future queue. 1071 func (pool *TxPool) demoteUnexecutables() { 1072 // Iterate over all accounts and demote any non-executable transactions 1073 for addr, list := range pool.pending { 1074 nonce := pool.currentState.GetNonce(addr) 1075 1076 // Drop all transactions that are deemed too old (low nonce) 1077 for _, tx := range list.Forward(nonce) { 1078 hash := tx.Hash() 1079 log.Trace("Removed old pending transaction", "hash", hash) 1080 delete(pool.all, hash) 1081 pool.priced.Removed() 1082 } 1083 // Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later 1084 drops, invalids := list.Filter(pool.currentState.GetBalance(addr), pool.currentMaxGas) 1085 for _, tx := range drops { 1086 hash := tx.Hash() 1087 log.Trace("Removed unpayable pending transaction", "hash", hash) 1088 delete(pool.all, hash) 1089 pool.priced.Removed() 1090 pendingNofundsCounter.Inc(1) 1091 } 1092 for _, tx := range invalids { 1093 hash := tx.Hash() 1094 log.Trace("Demoting pending transaction", "hash", hash) 1095 pool.enqueueTx(hash, tx) 1096 } 1097 // If there's a gap in front, warn (should never happen) and postpone all transactions 1098 if list.Len() > 0 && list.txs.Get(nonce) == nil { 1099 for _, tx := range list.Cap(0) { 1100 hash := tx.Hash() 1101 log.Error("Demoting invalidated transaction", "hash", hash) 1102 pool.enqueueTx(hash, tx) 1103 } 1104 } 1105 // Delete the entire queue entry if it became empty. 1106 if list.Empty() { 1107 delete(pool.pending, addr) 1108 delete(pool.beats, addr) 1109 } 1110 } 1111 } 1112 1113 // addressByHeartbeat is an account address tagged with its last activity timestamp. 1114 type addressByHeartbeat struct { 1115 address common.Address 1116 heartbeat time.Time 1117 } 1118 1119 type addresssByHeartbeat []addressByHeartbeat 1120 1121 func (a addresssByHeartbeat) Len() int { return len(a) } 1122 func (a addresssByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) } 1123 func (a addresssByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1124 1125 // accountSet is simply a set of addresses to check for existence, and a signer 1126 // capable of deriving addresses from transactions. 1127 type accountSet struct { 1128 accounts map[common.Address]struct{} 1129 signer types.Signer 1130 } 1131 1132 // newAccountSet creates a new address set with an associated signer for sender 1133 // derivations. 1134 func newAccountSet(signer types.Signer) *accountSet { 1135 return &accountSet{ 1136 accounts: make(map[common.Address]struct{}), 1137 signer: signer, 1138 } 1139 } 1140 1141 // contains checks if a given address is contained within the set. 1142 func (as *accountSet) contains(addr common.Address) bool { 1143 _, exist := as.accounts[addr] 1144 return exist 1145 } 1146 1147 // containsTx checks if the sender of a given tx is within the set. If the sender 1148 // cannot be derived, this method returns false. 1149 func (as *accountSet) containsTx(tx *types.Transaction) bool { 1150 if addr, err := types.Sender(as.signer, tx); err == nil { 1151 return as.contains(addr) 1152 } 1153 return false 1154 } 1155 1156 // add inserts a new address into the set to track. 1157 func (as *accountSet) add(addr common.Address) { 1158 as.accounts[addr] = struct{}{} 1159 }