| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 	maxQueued = 200 // max limit of queued txs per address | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 11:27:12 +02:00
										 |  |  | type stateFn func() *state.StateDB | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 	quit         chan bool // Quiting channel | 
					
						
							|  |  |  | 	currentState stateFn   // The state function which will allow us to do some pre checkes | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	mu      sync.RWMutex | 
					
						
							|  |  |  | 	pending map[common.Hash]*types.Transaction // processable transactions | 
					
						
							|  |  |  | 	queue   map[common.Address]map[common.Hash]*types.Transaction | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool { | 
					
						
							| 
									
										
										
										
											2015-06-09 23:46:56 +02:00
										 |  |  | 	pool := &TxPool{ | 
					
						
							| 
									
										
										
										
											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), | 
					
						
							|  |  |  | 		quit:         make(chan bool), | 
					
						
							|  |  |  | 		eventMux:     eventMux, | 
					
						
							|  |  |  | 		currentState: currentStateFn, | 
					
						
							|  |  |  | 		gasLimit:     gasLimitFn, | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		minGasPrice:  new(big.Int), | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 		pendingState: state.ManageState(currentStateFn()), | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		events:       eventMux.Subscribe(ChainEvent{}, GasPriceChanged{}), | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											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() { | 
					
						
							| 
									
										
										
										
											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-06-03 22:22:20 +02:00
										 |  |  | 		pool.mu.Lock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 		switch ev := ev.(type) { | 
					
						
							|  |  |  | 		case ChainEvent: | 
					
						
							|  |  |  | 			pool.resetState() | 
					
						
							|  |  |  | 		case GasPriceChanged: | 
					
						
							|  |  |  | 			pool.minGasPrice = ev.Price | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 		pool.mu.Unlock() | 
					
						
							| 
									
										
										
										
											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-06-09 18:14:46 +02:00
										 |  |  | 	pool.pendingState = state.ManageState(pool.currentState()) | 
					
						
							| 
									
										
										
										
											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-06-17 17:09:39 +02:00
										 |  |  | 			if pool.pendingState.GetNonce(addr) < tx.Nonce() { | 
					
						
							|  |  |  | 				pool.pendingState.SetNonce(addr, tx.Nonce()) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											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() { | 
					
						
							|  |  |  | 	close(pool.quit) | 
					
						
							|  |  |  | 	pool.events.Unsubscribe() | 
					
						
							|  |  |  | 	glog.V(logger.Info).Infoln("TX Pool stopped") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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-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-03-17 11:59:26 +01:00
										 |  |  | 	// Validate sender | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		from common.Address | 
					
						
							|  |  |  | 		err  error | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-15 11:33:08 +02:00
										 |  |  | 	// Drop transactions under our own minimal accepted gas price | 
					
						
							|  |  |  | 	if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { | 
					
						
							|  |  |  | 		return ErrCheap | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Validate the transaction sender and it's sig. Throw | 
					
						
							|  |  |  | 	// if the from fields is invalid. | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	if from, err = tx.From(); 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-04 16:19:22 +02:00
										 |  |  | 	// Make sure the account exist. Non existant accounts | 
					
						
							|  |  |  | 	// haven't got funds and well therefor never pass. | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	if !pool.currentState().HasAccount(from) { | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | 	if pool.currentState().GetNonce(from) > tx.Nonce() { | 
					
						
							|  |  |  | 		return ErrNonce | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Check the transaction doesn't exceed the current | 
					
						
							|  |  |  | 	// block limit gas. | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 	if pool.gasLimit().Cmp(tx.GasLimit) < 0 { | 
					
						
							|  |  |  | 		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-05-26 19:50:42 +02:00
										 |  |  | 	if tx.Amount.Cmp(common.Big0) < 0 { | 
					
						
							|  |  |  | 		return ErrNegativeValue | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Transactor should have enough funds to cover the costs | 
					
						
							|  |  |  | 	// cost == V + GP * GL | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 	total := new(big.Int).Mul(tx.Price, tx.GasLimit) | 
					
						
							|  |  |  | 	total.Add(total, tx.Value()) | 
					
						
							|  |  |  | 	if pool.currentState().GetBalance(from).Cmp(total) < 0 { | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		return ErrInsufficientFunds | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:19:22 +02:00
										 |  |  | 	// Should supply enough intrinsic gas | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 0 { | 
					
						
							|  |  |  | 		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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 	// check and validate the queueue | 
					
						
							|  |  |  | 	self.checkQueue() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  | 	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. | 
					
						
							|  |  |  | 		pool.pendingState.SetNonce(addr, tx.AccountNonce+1) | 
					
						
							|  |  |  | 		// 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-02-19 22:33:22 +01:00
										 |  |  | func (self *TxPool) Add(tx *types.Transaction) error { | 
					
						
							|  |  |  | 	self.mu.Lock() | 
					
						
							|  |  |  | 	defer self.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	return self.add(tx) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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-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 { | 
					
						
							|  |  |  | 	// 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
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	sort.Sort(types.TxByNonce{ret}) | 
					
						
							|  |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2015-05-05 23:09:18 +02:00
										 |  |  | 		self.removeTx(tx.Hash()) | 
					
						
							| 
									
										
										
										
											2014-10-27 16:52:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-06-09 18:14:46 +02:00
										 |  |  | 	state := pool.pendingState | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 	var addq txQueue | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	for address, txs := range pool.queue { | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 		// guessed nonce is the nonce currently kept by the tx pool (pending state) | 
					
						
							|  |  |  | 		guessedNonce := state.GetNonce(address) | 
					
						
							|  |  |  | 		// true nonce is the nonce known by the last state | 
					
						
							|  |  |  | 		trueNonce := pool.currentState().GetNonce(address) | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		addq := addq[:0] | 
					
						
							|  |  |  | 		for hash, tx := range txs { | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 			if tx.AccountNonce < trueNonce { | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 				// Drop queued transactions whose nonce is lower than | 
					
						
							|  |  |  | 				// the account nonce because they have been processed. | 
					
						
							|  |  |  | 				delete(txs, hash) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				// Collect the remaining transactions for the next pass. | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 				addq = append(addq, txQueueEntry{hash, address, tx}) | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		// Find the next consecutive nonce range starting at the | 
					
						
							|  |  |  | 		// current account nonce. | 
					
						
							|  |  |  | 		sort.Sort(addq) | 
					
						
							| 
									
										
										
										
											2015-06-15 16:46:45 +02:00
										 |  |  | 		for i, e := range addq { | 
					
						
							|  |  |  | 			// start deleting the transactions from the queue if they exceed the limit | 
					
						
							|  |  |  | 			if i > maxQueued { | 
					
						
							|  |  |  | 				if glog.V(logger.Debug) { | 
					
						
							|  |  |  | 					glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(e.hash[:])) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				delete(pool.queue[address], e.hash) | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 			if e.AccountNonce > guessedNonce { | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 			delete(txs, e.hash) | 
					
						
							| 
									
										
										
										
											2015-06-03 22:22:20 +02:00
										 |  |  | 			pool.addTx(e.hash, address, e.Transaction) | 
					
						
							| 
									
										
										
										
											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-04-30 00:20:59 +02:00
										 |  |  | func (pool *TxPool) removeTx(hash common.Hash) { | 
					
						
							|  |  |  | 	// delete from pending pool | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	delete(pool.pending, hash) | 
					
						
							| 
									
										
										
										
											2015-04-30 00:20:59 +02:00
										 |  |  | 	// delete from queue | 
					
						
							|  |  |  | 	for address, txs := range pool.queue { | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 		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) | 
					
						
							| 
									
										
										
										
											2015-04-30 00:20:59 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-03 14:06:20 +02:00
										 |  |  | 			break | 
					
						
							| 
									
										
										
										
											2015-04-30 00:20:59 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:23:31 +02:00
										 |  |  | // validatePool removes invalid and processed transactions from the main pool. | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | func (pool *TxPool) validatePool() { | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 	state := pool.currentState() | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 	for hash, tx := range pool.pending { | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 		from, _ := tx.From() // err already checked | 
					
						
							|  |  |  | 		// perform light nonce validation | 
					
						
							|  |  |  | 		if state.GetNonce(from) > tx.Nonce() { | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 			if glog.V(logger.Core) { | 
					
						
							| 
									
										
										
										
											2015-06-17 17:09:39 +02:00
										 |  |  | 				glog.Infof("removed tx (%x) from pool: low tx nonce\n", hash[:4]) | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-04 12:47:46 +02:00
										 |  |  | 			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] } | 
					
						
							|  |  |  | func (q txQueue) Less(i, j int) bool { return q[i].AccountNonce < q[j].AccountNonce } |