| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-01-31 17:22:17 +01:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/event" | 
					
						
							| 
									
										
										
										
											2014-10-31 12:56:05 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-31 17:22:17 +01:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | 	// Transaction Pool Errors | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	ErrInvalidSender      = errors.New("Invalid sender") | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	ErrNonce              = errors.New("Nonce too low") | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 	ErrCheap              = errors.New("Gas price too low for acceptance") | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 	ErrBalance            = errors.New("Insufficient balance") | 
					
						
							| 
									
										
										
										
											2015-05-11 01:28:15 +02:00
										 |  |  | 	ErrNonExistentAccount = errors.New("Account does not exist or account balance too low") | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 	ErrInsufficientFunds  = errors.New("Insufficient funds for gas * price + value") | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	ErrIntrinsicGas       = errors.New("Intrinsic gas too low") | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 	ErrGasLimit           = errors.New("Exceeds block gas limit") | 
					
						
							| 
									
										
										
										
											2015-05-26 19:50:42 +02:00
										 |  |  | 	ErrNegativeValue      = errors.New("Negative value") | 
					
						
							| 
									
										
										
										
											2015-01-31 17:22:17 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:54:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 12:16:29 +02:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 	maxQueued = 64 // max limit of queued txs per address | 
					
						
							| 
									
										
										
										
											2015-06-15 12:16:29 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | type stateFn func() (*state.StateDB, error) | 
					
						
							| 
									
										
										
										
											2015-04-21 11:27:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // TxPool contains all currently known transactions. Transactions | 
					
						
							|  |  |  | // enter the pool when they are received from the network or submitted | 
					
						
							|  |  |  | // locally. They exit the pool when they are included in the blockchain. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The pool separates processable transactions (which can be applied to the | 
					
						
							|  |  |  | // current state) and future transactions. Transactions move between those | 
					
						
							|  |  |  | // two states over time as they are received and processed. | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | type TxPool struct { | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 	config       *ChainConfig | 
					
						
							| 
									
										
										
										
											2016-03-29 03:08:16 +02:00
										 |  |  | 	currentState stateFn // The state function which will allow us to do some pre checks | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 	pendingState *state.ManagedState | 
					
						
							| 
									
										
										
										
											2015-06-03 14:20:44 +02:00
										 |  |  | 	gasLimit     func() *big.Int // The current gas limit function callback | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 	minGasPrice  *big.Int | 
					
						
							| 
									
										
										
										
											2015-06-03 14:20:44 +02:00
										 |  |  | 	eventMux     *event.TypeMux | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 	events       event.Subscription | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 	localTx      *txSet | 
					
						
							|  |  |  | 	mu           sync.RWMutex | 
					
						
							|  |  |  | 	pending      map[common.Hash]*types.Transaction // processable transactions | 
					
						
							|  |  |  | 	queue        map[common.Address]map[common.Hash]*types.Transaction | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-29 03:08:16 +02:00
										 |  |  | 	wg sync.WaitGroup // for shutdown sync | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 	homestead bool | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool { | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | 	pool := &TxPool{ | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 		config:       config, | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 		pending:      make(map[common.Hash]*types.Transaction), | 
					
						
							| 
									
										
										
										
											2015-06-03 14:20:44 +02:00
										 |  |  | 		queue:        make(map[common.Address]map[common.Hash]*types.Transaction), | 
					
						
							|  |  |  | 		eventMux:     eventMux, | 
					
						
							|  |  |  | 		currentState: currentStateFn, | 
					
						
							|  |  |  | 		gasLimit:     gasLimitFn, | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		minGasPrice:  new(big.Int), | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 		pendingState: nil, | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 		localTx:      newTxSet(), | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | 		events:       eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}), | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-29 03:08:16 +02:00
										 |  |  | 	pool.wg.Add(1) | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | 	go pool.eventLoop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pool | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | func (pool *TxPool) eventLoop() { | 
					
						
							| 
									
										
										
										
											2016-03-29 03:08:16 +02:00
										 |  |  | 	defer pool.wg.Done() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Track chain events. When a chain events occurs (new chain canon block) | 
					
						
							|  |  |  | 	// we need to know the new state. The new state will help us determine | 
					
						
							|  |  |  | 	// the nonces in the managed state | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 	for ev := range pool.events.Chan() { | 
					
						
							| 
									
										
										
										
											2015-10-12 15:04:38 +03:00
										 |  |  | 		switch ev := ev.Data.(type) { | 
					
						
							| 
									
										
										
										
											2015-06-30 15:42:20 +02:00
										 |  |  | 		case ChainHeadEvent: | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | 			pool.mu.Lock() | 
					
						
							| 
									
										
										
										
											2016-03-01 23:32:43 +01:00
										 |  |  | 			if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) { | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 				pool.homestead = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 			pool.resetState() | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | 			pool.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		case GasPriceChanged: | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | 			pool.mu.Lock() | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 			pool.minGasPrice = ev.Price | 
					
						
							| 
									
										
										
										
											2015-08-17 14:01:41 +02:00
										 |  |  | 			pool.mu.Unlock() | 
					
						
							|  |  |  | 		case RemovedTransactionEvent: | 
					
						
							|  |  |  | 			pool.AddTransactions(ev.Txs) | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 17:28:09 +02:00
										 |  |  | func (pool *TxPool) resetState() { | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	currentState, err := pool.currentState() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Info).Infoln("failed to get current state: %v", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	managedState := state.ManageState(currentState) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Info).Infoln("failed to get managed state: %v", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	pool.pendingState = managedState | 
					
						
							| 
									
										
										
										
											2015-06-04 17:28:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// validate the pool of pending transactions, this will remove | 
					
						
							|  |  |  | 	// any transactions that have been included in the block or | 
					
						
							|  |  |  | 	// have been invalidated because of another transaction (e.g. | 
					
						
							|  |  |  | 	// higher gas price) | 
					
						
							|  |  |  | 	pool.validatePool() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Loop over the pending transactions and base the nonce of the new | 
					
						
							|  |  |  | 	// pending transaction set. | 
					
						
							|  |  |  | 	for _, tx := range pool.pending { | 
					
						
							|  |  |  | 		if addr, err := tx.From(); err == nil { | 
					
						
							|  |  |  | 			// Set the nonce. Transaction nonce can never be lower | 
					
						
							|  |  |  | 			// than the state nonce; validatePool took care of that. | 
					
						
							| 
									
										
										
										
											2015-09-18 11:59:21 +02:00
										 |  |  | 			if pool.pendingState.GetNonce(addr) <= tx.Nonce() { | 
					
						
							|  |  |  | 				pool.pendingState.SetNonce(addr, tx.Nonce()+1) | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-04 17:28:09 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Check the queue and move transactions over to the pending if possible | 
					
						
							|  |  |  | 	// or remove those that have become invalid | 
					
						
							|  |  |  | 	pool.checkQueue() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | func (pool *TxPool) Stop() { | 
					
						
							|  |  |  | 	pool.events.Unsubscribe() | 
					
						
							| 
									
										
										
										
											2016-03-29 03:08:16 +02:00
										 |  |  | 	pool.wg.Wait() | 
					
						
							| 
									
										
										
										
											2015-08-01 17:34:48 +02:00
										 |  |  | 	glog.V(logger.Info).Infoln("Transaction pool stopped") | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) State() *state.ManagedState { | 
					
						
							|  |  |  | 	pool.mu.RLock() | 
					
						
							|  |  |  | 	defer pool.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 	return pool.pendingState | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | func (pool *TxPool) Stats() (pending int, queued int) { | 
					
						
							|  |  |  | 	pool.mu.RLock() | 
					
						
							|  |  |  | 	defer pool.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pending = len(pool.pending) | 
					
						
							|  |  |  | 	for _, txs := range pool.queue { | 
					
						
							|  |  |  | 		queued += len(txs) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 13:32:15 +02:00
										 |  |  | // Content retrieves the data content of the transaction pool, returning all the | 
					
						
							|  |  |  | // pending as well as queued transactions, grouped by account and nonce. | 
					
						
							|  |  |  | func (pool *TxPool) Content() (map[common.Address]map[uint64][]*types.Transaction, map[common.Address]map[uint64][]*types.Transaction) { | 
					
						
							|  |  |  | 	pool.mu.RLock() | 
					
						
							|  |  |  | 	defer pool.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Retrieve all the pending transactions and sort by account and by nonce | 
					
						
							|  |  |  | 	pending := make(map[common.Address]map[uint64][]*types.Transaction) | 
					
						
							|  |  |  | 	for _, tx := range pool.pending { | 
					
						
							|  |  |  | 		account, _ := tx.From() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		owned, ok := pending[account] | 
					
						
							|  |  |  | 		if !ok { | 
					
						
							|  |  |  | 			owned = make(map[uint64][]*types.Transaction) | 
					
						
							|  |  |  | 			pending[account] = owned | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		owned[tx.Nonce()] = append(owned[tx.Nonce()], tx) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Retrieve all the queued transactions and sort by account and by nonce | 
					
						
							|  |  |  | 	queued := make(map[common.Address]map[uint64][]*types.Transaction) | 
					
						
							|  |  |  | 	for account, txs := range pool.queue { | 
					
						
							|  |  |  | 		owned := make(map[uint64][]*types.Transaction) | 
					
						
							|  |  |  | 		for _, tx := range txs { | 
					
						
							|  |  |  | 			owned[tx.Nonce()] = append(owned[tx.Nonce()], tx) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		queued[account] = owned | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return pending, queued | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | // SetLocal marks a transaction as local, skipping gas price | 
					
						
							|  |  |  | //  check against local miner minimum in the future | 
					
						
							|  |  |  | func (pool *TxPool) SetLocal(tx *types.Transaction) { | 
					
						
							|  |  |  | 	pool.mu.Lock() | 
					
						
							|  |  |  | 	defer pool.mu.Unlock() | 
					
						
							|  |  |  | 	pool.localTx.add(tx.Hash()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // validateTx checks whether a transaction is valid according | 
					
						
							|  |  |  | // to the consensus rules. | 
					
						
							|  |  |  | func (pool *TxPool) validateTx(tx *types.Transaction) error { | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 	local := pool.localTx.contains(tx.Hash()) | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 	// Drop transactions under our own minimal accepted gas price | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 	if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		return ErrCheap | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	currentState, err := pool.currentState() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 	from, err := tx.From() | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-03-18 13:38:47 +01:00
										 |  |  | 		return ErrInvalidSender | 
					
						
							| 
									
										
										
										
											2014-12-02 00:14:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | 	// Make sure the account exist. Non existent accounts | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// haven't got funds and well therefor never pass. | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	if !currentState.HasAccount(from) { | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		return ErrNonExistentAccount | 
					
						
							| 
									
										
										
										
											2014-06-10 15:02:41 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 	// Last but not least check for nonce errors | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	if currentState.GetNonce(from) > tx.Nonce() { | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 		return ErrNonce | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Check the transaction doesn't exceed the current | 
					
						
							|  |  |  | 	// block limit gas. | 
					
						
							| 
									
										
										
										
											2015-06-11 14:05:32 +02:00
										 |  |  | 	if pool.gasLimit().Cmp(tx.Gas()) < 0 { | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 		return ErrGasLimit | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Transactions can't be negative. This may never happen | 
					
						
							|  |  |  | 	// using RLP decoded transactions but may occur if you create | 
					
						
							|  |  |  | 	// a transaction using the RPC for example. | 
					
						
							| 
									
										
										
										
											2015-06-11 14:05:32 +02:00
										 |  |  | 	if tx.Value().Cmp(common.Big0) < 0 { | 
					
						
							| 
									
										
										
										
											2015-05-26 19:50:42 +02:00
										 |  |  | 		return ErrNegativeValue | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Transactor should have enough funds to cover the costs | 
					
						
							|  |  |  | 	// cost == V + GP * GL | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 { | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		return ErrInsufficientFunds | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-19 23:50:00 +01:00
										 |  |  | 	intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	if tx.Gas().Cmp(intrGas) < 0 { | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		return ErrIntrinsicGas | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | // validate and queue transactions. | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | func (self *TxPool) add(tx *types.Transaction) error { | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	hash := tx.Hash() | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	if self.pending[hash] != nil { | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 		return fmt.Errorf("Known transaction (%x)", hash[:4]) | 
					
						
							| 
									
										
										
										
											2015-01-07 01:21:45 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | 	err := self.validateTx(tx) | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	self.queueTx(hash, tx) | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if glog.V(logger.Debug) { | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		var toname string | 
					
						
							|  |  |  | 		if to := tx.To(); to != nil { | 
					
						
							|  |  |  | 			toname = common.Bytes2Hex(to[:4]) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			toname = "[NEW_CONTRACT]" | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// we can ignore the error here because From is | 
					
						
							|  |  |  | 		// verified in ValidateTransaction. | 
					
						
							|  |  |  | 		f, _ := tx.From() | 
					
						
							|  |  |  | 		from := common.Bytes2Hex(f[:4]) | 
					
						
							|  |  |  | 		glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, hash) | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | // queueTx will queue an unknown transaction | 
					
						
							|  |  |  | func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) { | 
					
						
							|  |  |  | 	from, _ := tx.From() // already validated | 
					
						
							|  |  |  | 	if self.queue[from] == nil { | 
					
						
							|  |  |  | 		self.queue[from] = make(map[common.Hash]*types.Transaction) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	self.queue[from][hash] = tx | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // addTx will add a transaction to the pending (processable queue) list of transactions | 
					
						
							|  |  |  | func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) { | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	// init delayed since tx pool could have been started before any state sync | 
					
						
							|  |  |  | 	if pool.pendingState == nil { | 
					
						
							|  |  |  | 		pool.resetState() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | 	if _, ok := pool.pending[hash]; !ok { | 
					
						
							|  |  |  | 		pool.pending[hash] = tx | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Increment the nonce on the pending state. This can only happen if | 
					
						
							|  |  |  | 		// the nonce is +1 to the previous one. | 
					
						
							| 
									
										
										
										
											2015-06-11 14:05:32 +02:00
										 |  |  | 		pool.pendingState.SetNonce(addr, tx.Nonce()+1) | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | 		// Notify the subscribers. This event is posted in a goroutine | 
					
						
							|  |  |  | 		// because it's possible that somewhere during the post "Remove transaction" | 
					
						
							|  |  |  | 		// gets called which will then wait for the global tx pool lock and deadlock. | 
					
						
							|  |  |  | 		go pool.eventMux.Post(TxPreEvent{tx}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // Add queues a single transaction in the pool if it is valid. | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | func (self *TxPool) Add(tx *types.Transaction) error { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 	if err := self.add(tx); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 	self.checkQueue() | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // AddTransactions attempts to queue all valid transactions in txs. | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | func (self *TxPool) AddTransactions(txs []*types.Transaction) { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | 	for _, tx := range txs { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 		if err := self.add(tx); err != nil { | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 			glog.V(logger.Debug).Infoln("tx error:", err) | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 			h := tx.Hash() | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 			glog.V(logger.Debug).Infof("tx %x\n", h[:4]) | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-15 11:08:18 -07:00
										 |  |  | 	// check and validate the queue | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 	self.checkQueue() | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // GetTransaction returns a transaction if it is contained in the pool | 
					
						
							|  |  |  | // and nil otherwise. | 
					
						
							| 
									
										
										
										
											2015-05-07 17:27:17 +02:00
										 |  |  | func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { | 
					
						
							| 
									
										
										
										
											2016-06-02 20:33:45 +02:00
										 |  |  | 	tp.mu.RLock() | 
					
						
							|  |  |  | 	defer tp.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 17:27:17 +02:00
										 |  |  | 	// check the txs first | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	if tx, ok := tp.pending[hash]; ok { | 
					
						
							| 
									
										
										
										
											2015-05-07 17:27:17 +02:00
										 |  |  | 		return tx | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// check queue | 
					
						
							|  |  |  | 	for _, txs := range tp.queue { | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		if tx, ok := txs[hash]; ok { | 
					
						
							|  |  |  | 			return tx | 
					
						
							| 
									
										
										
										
											2015-05-07 17:27:17 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // GetTransactions returns all currently processable transactions. | 
					
						
							| 
									
										
										
										
											2015-06-09 17:03:07 +02:00
										 |  |  | // The returned slice may be modified by the caller. | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | func (self *TxPool) GetTransactions() (txs types.Transactions) { | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check queue first | 
					
						
							|  |  |  | 	self.checkQueue() | 
					
						
							|  |  |  | 	// invalidate any txs | 
					
						
							|  |  |  | 	self.validatePool() | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	txs = make(types.Transactions, len(self.pending)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	i := 0 | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	for _, tx := range self.pending { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 		txs[i] = tx | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		i++ | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	return txs | 
					
						
							| 
									
										
										
										
											2014-03-28 11:20:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // GetQueuedTransactions returns all non-processable transactions. | 
					
						
							| 
									
										
										
										
											2015-04-23 10:51:13 +02:00
										 |  |  | func (self *TxPool) GetQueuedTransactions() types.Transactions { | 
					
						
							|  |  |  | 	self.mu.RLock() | 
					
						
							|  |  |  | 	defer self.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	var ret types.Transactions | 
					
						
							|  |  |  | 	for _, txs := range self.queue { | 
					
						
							|  |  |  | 		for _, tx := range txs { | 
					
						
							|  |  |  | 			ret = append(ret, tx) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-23 10:51:13 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-22 12:05:17 +02:00
										 |  |  | 	sort.Sort(types.TxByNonce(ret)) | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	return ret | 
					
						
							| 
									
										
										
										
											2015-04-23 10:51:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // RemoveTransactions removes all given transactions from the pool. | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | func (self *TxPool) RemoveTransactions(txs types.Transactions) { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2014-10-27 16:52:58 +01:00
										 |  |  | 	for _, tx := range txs { | 
					
						
							| 
									
										
										
										
											2016-06-02 20:33:45 +02:00
										 |  |  | 		self.removeTx(tx.Hash()) | 
					
						
							| 
									
										
										
										
											2014-10-27 16:52:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-10 11:35:15 +02:00
										 |  |  | // RemoveTx removes the transaction with the given hash from the pool. | 
					
						
							|  |  |  | func (pool *TxPool) RemoveTx(hash common.Hash) { | 
					
						
							| 
									
										
										
										
											2016-06-02 20:33:45 +02:00
										 |  |  | 	pool.mu.Lock() | 
					
						
							|  |  |  | 	defer pool.mu.Unlock() | 
					
						
							|  |  |  | 	pool.removeTx(hash) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) removeTx(hash common.Hash) { | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 	// delete from pending pool | 
					
						
							|  |  |  | 	delete(pool.pending, hash) | 
					
						
							|  |  |  | 	// delete from queue | 
					
						
							|  |  |  | 	for address, txs := range pool.queue { | 
					
						
							|  |  |  | 		if _, ok := txs[hash]; ok { | 
					
						
							|  |  |  | 			if len(txs) == 1 { | 
					
						
							|  |  |  | 				// if only one tx, remove entire address entry. | 
					
						
							|  |  |  | 				delete(pool.queue, address) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				delete(txs, hash) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // checkQueue moves transactions that have become processable to main pool. | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | func (pool *TxPool) checkQueue() { | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	// init delayed since tx pool could have been started before any state sync | 
					
						
							|  |  |  | 	if pool.pendingState == nil { | 
					
						
							|  |  |  | 		pool.resetState() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 	var promote txQueue | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	for address, txs := range pool.queue { | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 		currentState, err := pool.currentState() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			glog.Errorf("could not get current state: %v", err) | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 		balance := currentState.GetBalance(address) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var ( | 
					
						
							|  |  |  | 			guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state) | 
					
						
							|  |  |  | 			trueNonce    = currentState.GetNonce(address)      // nonce known by the last state | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		promote = promote[:0] | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		for hash, tx := range txs { | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 			// Drop processed or out of fund transactions | 
					
						
							|  |  |  | 			if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 { | 
					
						
							|  |  |  | 				if glog.V(logger.Core) { | 
					
						
							|  |  |  | 					glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 				delete(txs, hash) | 
					
						
							| 
									
										
										
										
											2015-06-15 16:46:45 +02:00
										 |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 			// Collect the remaining transactions for the next pass. | 
					
						
							|  |  |  | 			promote = append(promote, txQueueEntry{hash, address, tx}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Find the next consecutive nonce range starting at the current account nonce, | 
					
						
							|  |  |  | 		// pushing the guessed nonce forward if we add consecutive transactions. | 
					
						
							|  |  |  | 		sort.Sort(promote) | 
					
						
							|  |  |  | 		for i, entry := range promote { | 
					
						
							|  |  |  | 			// If we reached a gap in the nonces, enforce transaction limit and stop | 
					
						
							|  |  |  | 			if entry.Nonce() > guessedNonce { | 
					
						
							|  |  |  | 				if len(promote)-i > maxQueued { | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 					if glog.V(logger.Debug) { | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 						glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:])) | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 					for _, drop := range promote[i+maxQueued:] { | 
					
						
							|  |  |  | 						delete(txs, drop.hash) | 
					
						
							| 
									
										
										
										
											2015-06-30 11:04:30 +02:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 			// Otherwise promote the transaction and move the guess nonce if needed | 
					
						
							|  |  |  | 			pool.addTx(entry.hash, address, entry.Transaction) | 
					
						
							|  |  |  | 			delete(txs, entry.hash) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if entry.Nonce() == guessedNonce { | 
					
						
							|  |  |  | 				guessedNonce++ | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		// Delete the entire queue entry if it became empty. | 
					
						
							|  |  |  | 		if len(txs) == 0 { | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 			delete(pool.queue, address) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // validatePool removes invalid and processed transactions from the main pool. | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | // If a transaction is removed for being invalid (e.g. out of funds), all sub- | 
					
						
							|  |  |  | // sequent (Still valid) transactions are moved back into the future queue. This | 
					
						
							|  |  |  | // is important to prevent a drained account from DOSing the network with non | 
					
						
							|  |  |  | // executable transactions. | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | func (pool *TxPool) validatePool() { | 
					
						
							| 
									
										
										
										
											2015-10-06 16:35:55 +02:00
										 |  |  | 	state, err := pool.currentState() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Info).Infoln("failed to get current state: %v", err) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 	balanceCache := make(map[common.Address]*big.Int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Clean up the pending pool, accumulating invalid nonces | 
					
						
							|  |  |  | 	gaps := make(map[common.Address]uint64) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	for hash, tx := range pool.pending { | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 		sender, _ := tx.From() // err already checked | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Perform light nonce and balance validation | 
					
						
							|  |  |  | 		balance := balanceCache[sender] | 
					
						
							|  |  |  | 		if balance == nil { | 
					
						
							|  |  |  | 			balance = state.GetBalance(sender) | 
					
						
							|  |  |  | 			balanceCache[sender] = balance | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 { | 
					
						
							|  |  |  | 			// Remove an already past it invalidated transaction | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 			if glog.V(logger.Core) { | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 				glog.Infof("removed tx (%v) from pool: low tx nonce or out of funds\n", tx) | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 			delete(pool.pending, hash) | 
					
						
							| 
									
										
										
										
											2015-12-30 18:31:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Track the smallest invalid nonce to postpone subsequent transactions | 
					
						
							|  |  |  | 			if !past { | 
					
						
							|  |  |  | 				if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev { | 
					
						
							|  |  |  | 					gaps[sender] = tx.Nonce() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Move all transactions after a gap back to the future queue | 
					
						
							|  |  |  | 	if len(gaps) > 0 { | 
					
						
							|  |  |  | 		for hash, tx := range pool.pending { | 
					
						
							|  |  |  | 			sender, _ := tx.From() | 
					
						
							|  |  |  | 			if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap { | 
					
						
							|  |  |  | 				if glog.V(logger.Core) { | 
					
						
							|  |  |  | 					glog.Infof("postponed tx (%v) due to introduced gap\n", tx) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				pool.queueTx(hash, tx) | 
					
						
							|  |  |  | 				delete(pool.pending, hash) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | type txQueue []txQueueEntry | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type txQueueEntry struct { | 
					
						
							|  |  |  | 	hash common.Hash | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 	addr common.Address | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	*types.Transaction | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (q txQueue) Len() int           { return len(q) } | 
					
						
							|  |  |  | func (q txQueue) Swap(i, j int)      { q[i], q[j] = q[j], q[i] } | 
					
						
							| 
									
										
										
										
											2015-06-11 14:05:32 +02:00
										 |  |  | func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() } | 
					
						
							| 
									
										
										
										
											2015-11-21 00:40:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // txSet represents a set of transaction hashes in which entries | 
					
						
							|  |  |  | //  are automatically dropped after txSetDuration time | 
					
						
							|  |  |  | type txSet struct { | 
					
						
							|  |  |  | 	txMap          map[common.Hash]struct{} | 
					
						
							|  |  |  | 	txOrd          map[uint64]txOrdType | 
					
						
							|  |  |  | 	addPtr, delPtr uint64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const txSetDuration = time.Hour * 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // txOrdType represents an entry in the time-ordered list of transaction hashes | 
					
						
							|  |  |  | type txOrdType struct { | 
					
						
							|  |  |  | 	hash common.Hash | 
					
						
							|  |  |  | 	time time.Time | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // newTxSet creates a new transaction set | 
					
						
							|  |  |  | func newTxSet() *txSet { | 
					
						
							|  |  |  | 	return &txSet{ | 
					
						
							|  |  |  | 		txMap: make(map[common.Hash]struct{}), | 
					
						
							|  |  |  | 		txOrd: make(map[uint64]txOrdType), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // contains returns true if the set contains the given transaction hash | 
					
						
							|  |  |  | // (not thread safe, should be called from a locked environment) | 
					
						
							|  |  |  | func (self *txSet) contains(hash common.Hash) bool { | 
					
						
							|  |  |  | 	_, ok := self.txMap[hash] | 
					
						
							|  |  |  | 	return ok | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // add adds a transaction hash to the set, then removes entries older than txSetDuration | 
					
						
							|  |  |  | // (not thread safe, should be called from a locked environment) | 
					
						
							|  |  |  | func (self *txSet) add(hash common.Hash) { | 
					
						
							|  |  |  | 	self.txMap[hash] = struct{}{} | 
					
						
							|  |  |  | 	now := time.Now() | 
					
						
							|  |  |  | 	self.txOrd[self.addPtr] = txOrdType{hash: hash, time: now} | 
					
						
							|  |  |  | 	self.addPtr++ | 
					
						
							|  |  |  | 	delBefore := now.Add(-txSetDuration) | 
					
						
							|  |  |  | 	for self.delPtr < self.addPtr && self.txOrd[self.delPtr].time.Before(delBefore) { | 
					
						
							|  |  |  | 		delete(self.txMap, self.txOrd[self.delPtr].hash) | 
					
						
							|  |  |  | 		delete(self.txOrd, self.delPtr) | 
					
						
							|  |  |  | 		self.delPtr++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |