github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/tx_pool.go (about) 1 // Copyright 2014 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 17 package core 18 19 import ( 20 "errors" 21 "fmt" 22 "math/big" 23 "sort" 24 "sync" 25 "time" 26 27 "github.com/ethereumproject/go-ethereum/common" 28 "github.com/ethereumproject/go-ethereum/core/state" 29 "github.com/ethereumproject/go-ethereum/core/types" 30 "github.com/ethereumproject/go-ethereum/event" 31 "github.com/ethereumproject/go-ethereum/logger" 32 "github.com/ethereumproject/go-ethereum/logger/glog" 33 ) 34 35 var ( 36 // Transaction Pool Errors 37 ErrInvalidSender = errors.New("Invalid sender") 38 ErrNonce = errors.New("Nonce too low") 39 ErrCheap = errors.New("Gas price too low for acceptance") 40 ErrBalance = errors.New("Insufficient balance") 41 ErrNonExistentAccount = errors.New("Account does not exist or account balance too low") 42 ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value") 43 ErrIntrinsicGas = errors.New("Intrinsic gas too low") 44 ErrGasLimit = errors.New("Exceeds block gas limit") 45 ErrNegativeValue = errors.New("Negative value") 46 ) 47 48 const ( 49 maxQueued = 64 // max limit of queued txs per address 50 ) 51 52 type stateFn func() (*state.StateDB, error) 53 54 // TxPool contains all currently known transactions. Transactions 55 // enter the pool when they are received from the network or submitted 56 // locally. They exit the pool when they are included in the blockchain. 57 // 58 // The pool separates processable transactions (which can be applied to the 59 // current state) and future transactions. Transactions move between those 60 // two states over time as they are received and processed. 61 type TxPool struct { 62 config *ChainConfig 63 signer types.Signer 64 currentState stateFn // The state function which will allow us to do some pre checks 65 pendingState *state.ManagedState 66 gasLimit func() *big.Int // The current gas limit function callback 67 minGasPrice *big.Int 68 eventMux *event.TypeMux 69 events event.Subscription 70 localTx *txSet 71 mu sync.RWMutex 72 pending map[common.Hash]*types.Transaction // processable transactions 73 queue map[common.Address]map[common.Hash]*types.Transaction 74 75 wg sync.WaitGroup // for shutdown sync 76 77 homestead bool 78 } 79 80 func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool { 81 pool := &TxPool{ 82 config: config, 83 signer: types.NewChainIdSigner(config.GetChainID()), 84 pending: make(map[common.Hash]*types.Transaction), 85 queue: make(map[common.Address]map[common.Hash]*types.Transaction), 86 eventMux: eventMux, 87 currentState: currentStateFn, 88 gasLimit: gasLimitFn, 89 minGasPrice: new(big.Int), 90 pendingState: nil, 91 localTx: newTxSet(), 92 events: eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}), 93 } 94 95 pool.wg.Add(1) 96 go pool.eventLoop() 97 98 return pool 99 } 100 101 func (pool *TxPool) eventLoop() { 102 defer pool.wg.Done() 103 104 // Track chain events. When a chain events occurs (new chain canon block) 105 // we need to know the new state. The new state will help us determine 106 // the nonces in the managed state 107 for ev := range pool.events.Chan() { 108 switch ev := ev.Data.(type) { 109 case ChainHeadEvent: 110 pool.mu.Lock() 111 if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) { 112 pool.homestead = true 113 } 114 115 pool.resetState() 116 pool.mu.Unlock() 117 case GasPriceChanged: 118 pool.mu.Lock() 119 pool.minGasPrice = ev.Price 120 pool.mu.Unlock() 121 case RemovedTransactionEvent: 122 pool.AddTransactions(ev.Txs) 123 } 124 } 125 } 126 127 func (pool *TxPool) resetState() { 128 currentState, err := pool.currentState() 129 if err != nil { 130 glog.V(logger.Info).Infof("failed to get current state: %v", err) 131 return 132 } 133 managedState := state.ManageState(currentState) 134 if err != nil { 135 glog.V(logger.Info).Infof("failed to get managed state: %v", err) 136 return 137 } 138 pool.pendingState = managedState 139 140 // validate the pool of pending transactions, this will remove 141 // any transactions that have been included in the block or 142 // have been invalidated because of another transaction (e.g. 143 // higher gas price) 144 pool.validatePool() 145 146 // Loop over the pending transactions and base the nonce of the new 147 // pending transaction set. 148 for _, tx := range pool.pending { 149 if addr, err := tx.From(); err == nil { 150 // Set the nonce. Transaction nonce can never be lower 151 // than the state nonce; validatePool took care of that. 152 if pool.pendingState.GetNonce(addr) <= tx.Nonce() { 153 pool.pendingState.SetNonce(addr, tx.Nonce()+1) 154 } 155 } 156 } 157 // Check the queue and move transactions over to the pending if possible 158 // or remove those that have become invalid 159 pool.checkQueue() 160 } 161 162 func (pool *TxPool) Stop() { 163 pool.events.Unsubscribe() 164 pool.wg.Wait() 165 glog.V(logger.Info).Infoln("Transaction pool stopped") 166 } 167 168 func (pool *TxPool) State() *state.ManagedState { 169 pool.mu.RLock() 170 defer pool.mu.RUnlock() 171 172 return pool.pendingState 173 } 174 175 func (pool *TxPool) Stats() (pending int, queued int) { 176 pool.mu.RLock() 177 defer pool.mu.RUnlock() 178 179 pending = len(pool.pending) 180 for _, txs := range pool.queue { 181 queued += len(txs) 182 } 183 return 184 } 185 186 // Content retrieves the data content of the transaction pool, returning all the 187 // pending as well as queued transactions, grouped by account and nonce. 188 func (pool *TxPool) Content() (map[common.Address]map[uint64][]*types.Transaction, map[common.Address]map[uint64][]*types.Transaction) { 189 pool.mu.RLock() 190 defer pool.mu.RUnlock() 191 192 // Retrieve all the pending transactions and sort by account and by nonce 193 pending := make(map[common.Address]map[uint64][]*types.Transaction) 194 for _, tx := range pool.pending { 195 account, _ := tx.From() 196 197 owned, ok := pending[account] 198 if !ok { 199 owned = make(map[uint64][]*types.Transaction) 200 pending[account] = owned 201 } 202 owned[tx.Nonce()] = append(owned[tx.Nonce()], tx) 203 } 204 // Retrieve all the queued transactions and sort by account and by nonce 205 queued := make(map[common.Address]map[uint64][]*types.Transaction) 206 for account, txs := range pool.queue { 207 owned := make(map[uint64][]*types.Transaction) 208 for _, tx := range txs { 209 owned[tx.Nonce()] = append(owned[tx.Nonce()], tx) 210 } 211 queued[account] = owned 212 } 213 return pending, queued 214 } 215 216 // SetLocal marks a transaction as local, skipping gas price 217 // check against local miner minimum in the future 218 func (pool *TxPool) SetLocal(tx *types.Transaction) { 219 pool.mu.Lock() 220 defer pool.mu.Unlock() 221 pool.localTx.add(tx.Hash()) 222 } 223 224 // validateTx checks whether a transaction is valid according 225 // to the consensus rules. 226 func (pool *TxPool) validateTx(tx *types.Transaction) (e error) { 227 local := pool.localTx.contains(tx.Hash()) 228 defer func() { 229 mlogTxPoolValidateTx.AssignDetails( 230 tx.Hash().Hex(), 231 tx.Size(), 232 common.StorageSize(len(tx.Data())), 233 tx.Nonce(), 234 tx.Gas(), 235 tx.GasPrice(), 236 e == nil, 237 e, 238 ).Send(mlogTxPool) 239 }() 240 // Drop transactions under our own minimal accepted gas price 241 if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { 242 e = ErrCheap 243 return 244 } 245 246 currentState, err := pool.currentState() 247 if err != nil { 248 e = err 249 return 250 } 251 252 from, err := types.Sender(pool.signer, tx) 253 if err != nil { 254 e = ErrInvalidSender 255 return 256 } 257 258 // Make sure the account exist. Non existent accounts 259 // haven't got funds and well therefor never pass. 260 if !currentState.Exist(from) { 261 e = ErrNonExistentAccount 262 return 263 } 264 265 // Last but not least check for nonce errors 266 if currentState.GetNonce(from) > tx.Nonce() { 267 e = ErrNonce 268 return 269 } 270 271 // Check the transaction doesn't exceed the current 272 // block limit gas. 273 if pool.gasLimit().Cmp(tx.Gas()) < 0 { 274 e = ErrGasLimit 275 return 276 } 277 278 // Transactions can't be negative. This may never happen 279 // using RLP decoded transactions but may occur if you create 280 // a transaction using the RPC for example. 281 if tx.Value().Sign() < 0 { 282 e = ErrNegativeValue 283 return 284 } 285 286 // Transactor should have enough funds to cover the costs 287 // cost == V + GP * GL 288 if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { 289 e = ErrInsufficientFunds 290 return 291 } 292 293 intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead) 294 if tx.Gas().Cmp(intrGas) < 0 { 295 e = ErrIntrinsicGas 296 return 297 } 298 return // e=nil 299 } 300 301 // validate and queue transactions. 302 func (self *TxPool) add(tx *types.Transaction) error { 303 hash := tx.Hash() 304 305 if self.pending[hash] != nil { 306 return fmt.Errorf("Known transaction (%x)", hash[:4]) 307 } 308 err := self.validateTx(tx) 309 if err != nil { 310 return err 311 } 312 self.queueTx(hash, tx) 313 314 var toName, toLogName string 315 if to := tx.To(); to != nil { 316 toName = common.Bytes2Hex(to[:4]) 317 toLogName = tx.To().Hex() 318 } else { 319 toName = "[NEW_CONTRACT]" 320 toLogName = "[NEW_CONTRACT]" 321 } 322 // we can ignore the error here because From is 323 // verified in ValidateTransaction. 324 f, _ := types.Sender(self.signer, tx) 325 from := common.Bytes2Hex(f[:4]) 326 327 if logger.MlogEnabled() { 328 mlogTxPoolAddTx.AssignDetails( 329 f.Hex(), 330 toLogName, 331 tx.Value, 332 hash.Hex(), 333 ).Send(mlogTxPool) 334 } 335 if glog.V(logger.Debug) { 336 glog.Infof("(t) %x => %s (%v) %x\n", from, toName, tx.Value(), hash) 337 } 338 339 return nil 340 } 341 342 // queueTx will queue an unknown transaction 343 func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) { 344 from, _ := types.Sender(self.signer, tx) // already validated 345 if self.queue[from] == nil { 346 self.queue[from] = make(map[common.Hash]*types.Transaction) 347 } 348 self.queue[from][hash] = tx 349 } 350 351 // addTx will add a transaction to the pending (processable queue) list of transactions 352 func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) { 353 // init delayed since tx pool could have been started before any state sync 354 if pool.pendingState == nil { 355 pool.resetState() 356 } 357 358 if _, ok := pool.pending[hash]; !ok { 359 pool.pending[hash] = tx 360 361 // Increment the nonce on the pending state. This can only happen if 362 // the nonce is +1 to the previous one. 363 pool.pendingState.SetNonce(addr, tx.Nonce()+1) 364 // Notify the subscribers. This event is posted in a goroutine 365 // because it's possible that somewhere during the post "Remove transaction" 366 // gets called which will then wait for the global tx pool lock and deadlock. 367 go pool.eventMux.Post(TxPreEvent{tx}) 368 } 369 } 370 371 // Add queues a single transaction in the pool if it is valid. 372 func (self *TxPool) Add(tx *types.Transaction) error { 373 self.mu.Lock() 374 defer self.mu.Unlock() 375 376 if err := self.add(tx); err != nil { 377 return err 378 } 379 self.checkQueue() 380 return nil 381 } 382 383 // AddTransactions attempts to queue all valid transactions in txs. 384 func (self *TxPool) AddTransactions(txs []*types.Transaction) { 385 self.mu.Lock() 386 defer self.mu.Unlock() 387 388 for _, tx := range txs { 389 if err := self.add(tx); err != nil { 390 glog.V(logger.Debug).Infoln("tx error:", err) 391 } else { 392 h := tx.Hash() 393 glog.V(logger.Debug).Infof("tx %x\n", h[:4]) 394 } 395 } 396 397 // check and validate the queue 398 self.checkQueue() 399 } 400 401 // GetTransaction returns a transaction if it is contained in the pool 402 // and nil otherwise. 403 func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { 404 tp.mu.RLock() 405 defer tp.mu.RUnlock() 406 407 // check the txs first 408 if tx, ok := tp.pending[hash]; ok { 409 return tx 410 } 411 // check queue 412 for _, txs := range tp.queue { 413 if tx, ok := txs[hash]; ok { 414 return tx 415 } 416 } 417 return nil 418 } 419 420 // GetTransactions returns all currently processable transactions. 421 // The returned slice may be modified by the caller. 422 func (self *TxPool) GetTransactions() (txs types.Transactions) { 423 self.mu.Lock() 424 defer self.mu.Unlock() 425 426 // check queue first 427 self.checkQueue() 428 // invalidate any txs 429 self.validatePool() 430 431 txs = make(types.Transactions, len(self.pending)) 432 i := 0 433 for _, tx := range self.pending { 434 txs[i] = tx 435 i++ 436 } 437 return txs 438 } 439 440 // GetQueuedTransactions returns all non-processable transactions. 441 func (self *TxPool) GetQueuedTransactions() types.Transactions { 442 self.mu.RLock() 443 defer self.mu.RUnlock() 444 445 var ret types.Transactions 446 for _, txs := range self.queue { 447 for _, tx := range txs { 448 ret = append(ret, tx) 449 } 450 } 451 sort.Sort(types.TxByNonce(ret)) 452 return ret 453 } 454 455 // RemoveTransactions removes all given transactions from the pool. 456 func (self *TxPool) RemoveTransactions(txs types.Transactions) { 457 self.mu.Lock() 458 defer self.mu.Unlock() 459 for _, tx := range txs { 460 self.removeTx(tx.Hash()) 461 } 462 } 463 464 // RemoveTx removes the transaction with the given hash from the pool. 465 func (pool *TxPool) RemoveTx(hash common.Hash) { 466 pool.mu.Lock() 467 defer pool.mu.Unlock() 468 pool.removeTx(hash) 469 } 470 471 func (pool *TxPool) removeTx(hash common.Hash) { 472 // delete from pending pool 473 delete(pool.pending, hash) 474 // delete from queue 475 for address, txs := range pool.queue { 476 if _, ok := txs[hash]; ok { 477 if len(txs) == 1 { 478 // if only one tx, remove entire address entry. 479 delete(pool.queue, address) 480 } else { 481 delete(txs, hash) 482 } 483 break 484 } 485 } 486 } 487 488 // checkQueue moves transactions that have become processable to main pool. 489 func (pool *TxPool) checkQueue() { 490 // init delayed since tx pool could have been started before any state sync 491 if pool.pendingState == nil { 492 pool.resetState() 493 } 494 495 var promote txQueue 496 for address, txs := range pool.queue { 497 currentState, err := pool.currentState() 498 if err != nil { 499 glog.Errorf("could not get current state: %v", err) 500 return 501 } 502 balance := currentState.GetBalance(address) 503 504 var ( 505 guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state) 506 trueNonce = currentState.GetNonce(address) // nonce known by the last state 507 ) 508 promote = promote[:0] 509 for hash, tx := range txs { 510 // Drop processed or out of fund transactions 511 if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 { 512 if glog.V(logger.Core) { 513 glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx) 514 } 515 delete(txs, hash) 516 continue 517 } 518 // Collect the remaining transactions for the next pass. 519 promote = append(promote, txQueueEntry{hash, address, tx}) 520 } 521 // Find the next consecutive nonce range starting at the current account nonce, 522 // pushing the guessed nonce forward if we add consecutive transactions. 523 sort.Sort(promote) 524 for i, entry := range promote { 525 // If we reached a gap in the nonces, enforce transaction limit and stop 526 if entry.Nonce() > guessedNonce { 527 if len(promote)-i > maxQueued { 528 if glog.V(logger.Debug) { 529 glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:])) 530 } 531 for _, drop := range promote[i+maxQueued:] { 532 delete(txs, drop.hash) 533 } 534 } 535 break 536 } 537 // Otherwise promote the transaction and move the guess nonce if needed 538 pool.addTx(entry.hash, address, entry.Transaction) 539 delete(txs, entry.hash) 540 541 if entry.Nonce() == guessedNonce { 542 guessedNonce++ 543 } 544 } 545 // Delete the entire queue entry if it became empty. 546 if len(txs) == 0 { 547 delete(pool.queue, address) 548 } 549 } 550 } 551 552 // validatePool removes invalid and processed transactions from the main pool. 553 // If a transaction is removed for being invalid (e.g. out of funds), all sub- 554 // sequent (Still valid) transactions are moved back into the future queue. This 555 // is important to prevent a drained account from DOSing the network with non 556 // executable transactions. 557 func (pool *TxPool) validatePool() { 558 state, err := pool.currentState() 559 if err != nil { 560 glog.V(logger.Info).Infof("failed to get current state: %v", err) 561 return 562 } 563 balanceCache := make(map[common.Address]*big.Int) 564 565 // Clean up the pending pool, accumulating invalid nonces 566 gaps := make(map[common.Address]uint64) 567 568 for hash, tx := range pool.pending { 569 sender, _ := tx.From() // err already checked 570 571 // Perform light nonce and balance validation 572 balance := balanceCache[sender] 573 if balance == nil { 574 balance = state.GetBalance(sender) 575 balanceCache[sender] = balance 576 } 577 if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 { 578 // Remove an already past it invalidated transaction 579 if glog.V(logger.Core) { 580 glog.Infof("removed tx (%v) from pool: low tx nonce or out of funds\n", tx) 581 } 582 delete(pool.pending, hash) 583 584 // Track the smallest invalid nonce to postpone subsequent transactions 585 if !past { 586 if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev { 587 gaps[sender] = tx.Nonce() 588 } 589 } 590 } 591 } 592 // Move all transactions after a gap back to the future queue 593 if len(gaps) > 0 { 594 for hash, tx := range pool.pending { 595 sender, _ := tx.From() 596 if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap { 597 if glog.V(logger.Core) { 598 glog.Infof("postponed tx (%v) due to introduced gap\n", tx) 599 } 600 pool.queueTx(hash, tx) 601 delete(pool.pending, hash) 602 } 603 } 604 } 605 } 606 607 type txQueue []txQueueEntry 608 609 type txQueueEntry struct { 610 hash common.Hash 611 addr common.Address 612 *types.Transaction 613 } 614 615 func (q txQueue) Len() int { return len(q) } 616 func (q txQueue) Swap(i, j int) { q[i], q[j] = q[j], q[i] } 617 func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() } 618 619 // txSet represents a set of transaction hashes in which entries 620 // are automatically dropped after txSetDuration time 621 type txSet struct { 622 txMap map[common.Hash]struct{} 623 txOrd map[uint64]txOrdType 624 addPtr, delPtr uint64 625 } 626 627 const txSetDuration = time.Hour * 2 628 629 // txOrdType represents an entry in the time-ordered list of transaction hashes 630 type txOrdType struct { 631 hash common.Hash 632 time time.Time 633 } 634 635 // newTxSet creates a new transaction set 636 func newTxSet() *txSet { 637 return &txSet{ 638 txMap: make(map[common.Hash]struct{}), 639 txOrd: make(map[uint64]txOrdType), 640 } 641 } 642 643 // contains returns true if the set contains the given transaction hash 644 // (not thread safe, should be called from a locked environment) 645 func (self *txSet) contains(hash common.Hash) bool { 646 _, ok := self.txMap[hash] 647 return ok 648 } 649 650 // add adds a transaction hash to the set, then removes entries older than txSetDuration 651 // (not thread safe, should be called from a locked environment) 652 func (self *txSet) add(hash common.Hash) { 653 self.txMap[hash] = struct{}{} 654 now := time.Now() 655 self.txOrd[self.addPtr] = txOrdType{hash: hash, time: now} 656 self.addPtr++ 657 delBefore := now.Add(-txSetDuration) 658 for self.delPtr < self.addPtr && self.txOrd[self.delPtr].time.Before(delBefore) { 659 delete(self.txMap, self.txOrd[self.delPtr].hash) 660 delete(self.txOrd, self.delPtr) 661 self.delPtr++ 662 } 663 }