| 
									
										
										
										
											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-04-21 22:01:04 +02: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" | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 	"gopkg.in/fatih/set.v0" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-31 17:22:17 +01:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											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-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-01-31 17:22:17 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2014-06-23 12:54:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-29 03:50:20 +01:00
										 |  |  | const txPoolQueueSize = 50 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | type TxPoolHook chan *types.Transaction | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | type TxMsg struct{ Tx *types.Transaction } | 
					
						
							| 
									
										
										
										
											2014-02-25 11:22:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 11:27:12 +02:00
										 |  |  | type stateFn func() *state.StateDB | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-25 11:22:27 +01:00
										 |  |  | const ( | 
					
						
							| 
									
										
										
										
											2014-06-10 15:02:41 +02:00
										 |  |  | 	minGasPrice = 1000000 | 
					
						
							| 
									
										
										
										
											2014-02-25 11:22:27 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 01:57:04 +01:00
										 |  |  | type TxProcessor interface { | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | 	ProcessTransaction(tx *types.Transaction) | 
					
						
							| 
									
										
										
										
											2014-02-23 01:57:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | // The tx pool a thread safe transaction pool handler. In order to | 
					
						
							|  |  |  | // guarantee a non blocking pool we use a queue channel which can be | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | // independently read without needing access to the actual pool. | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | type TxPool struct { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	mu sync.RWMutex | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Queueing channel for reading and writing incoming | 
					
						
							|  |  |  | 	// transactions to | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | 	queueChan chan *types.Transaction | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Quiting channel | 
					
						
							|  |  |  | 	quit chan bool | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	// The state function which will allow us to do some pre checkes | 
					
						
							| 
									
										
										
										
											2015-04-21 11:27:12 +02:00
										 |  |  | 	currentState stateFn | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 	// The current gas limit function callback | 
					
						
							|  |  |  | 	gasLimit func() *big.Int | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// The actual pool | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 	txs           map[common.Hash]*types.Transaction | 
					
						
							|  |  |  | 	invalidHashes *set.Set | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	queue map[common.Address]types.Transactions | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-25 11:22:27 +01:00
										 |  |  | 	subscribers []chan TxMsg | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 12:26:55 +01:00
										 |  |  | 	eventMux *event.TypeMux | 
					
						
							| 
									
										
										
										
											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-04-21 22:01:04 +02:00
										 |  |  | 	txPool := &TxPool{ | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 		txs:           make(map[common.Hash]*types.Transaction), | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 		queue:         make(map[common.Address]types.Transactions), | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 		queueChan:     make(chan *types.Transaction, txPoolQueueSize), | 
					
						
							|  |  |  | 		quit:          make(chan bool), | 
					
						
							|  |  |  | 		eventMux:      eventMux, | 
					
						
							|  |  |  | 		invalidHashes: set.New(), | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		currentState:  currentStateFn, | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 		gasLimit:      gasLimitFn, | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	return txPool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) Start() { | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 	// Queue timer will tick so we can attempt to move items from the queue to the | 
					
						
							|  |  |  | 	// main transaction pool. | 
					
						
							|  |  |  | 	queueTimer := time.NewTicker(300 * time.Millisecond) | 
					
						
							|  |  |  | 	// Removal timer will tick and attempt to remove bad transactions (account.nonce>tx.nonce) | 
					
						
							|  |  |  | 	removalTimer := time.NewTicker(1 * time.Second) | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | done: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 		case <-queueTimer.C: | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 			pool.checkQueue() | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 		case <-removalTimer.C: | 
					
						
							|  |  |  | 			pool.validatePool() | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 		case <-pool.quit: | 
					
						
							|  |  |  | 			break done | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | func (pool *TxPool) ValidateTransaction(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 | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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-01-31 17:22:17 +01:00
										 |  |  | 	// Validate curve param | 
					
						
							| 
									
										
										
										
											2014-12-03 14:05:19 +01:00
										 |  |  | 	v, _, _ := tx.Curve() | 
					
						
							|  |  |  | 	if v > 28 || v < 27 { | 
					
						
							| 
									
										
										
										
											2015-01-02 12:24:36 +01:00
										 |  |  | 		return fmt.Errorf("tx.v != (28 || 27) => %v", v) | 
					
						
							| 
									
										
										
										
											2014-06-12 10:07:27 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-31 17:22:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-04-24 17:45:51 +02:00
										 |  |  | 	if pool.gasLimit().Cmp(tx.GasLimit) < 0 { | 
					
						
							|  |  |  | 		return ErrGasLimit | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 0 { | 
					
						
							|  |  |  | 		return ErrIntrinsicGas | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if pool.currentState().GetNonce(from) > tx.Nonce() { | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 		return ErrNonce | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-04-08 20:47:32 +02:00
										 |  |  | 	/* XXX I'm unsure about this. This is extremely dangerous and may result | 
					
						
							|  |  |  | 	 in total black listing of certain transactions | 
					
						
							| 
									
										
										
										
											2015-04-08 00:31:23 +02:00
										 |  |  | 	if self.invalidHashes.Has(hash) { | 
					
						
							|  |  |  | 		return fmt.Errorf("Invalid transaction (%x)", hash[:4]) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	if self.txs[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
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 	err := self.ValidateTransaction(tx) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 23:20:27 +02:00
										 |  |  | 	self.queueTx(tx) | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 	var toname string | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	if to := tx.To(); to != nil { | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 		toname = common.Bytes2Hex(to[:4]) | 
					
						
							| 
									
										
										
										
											2015-01-02 22:19:58 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 		toname = "[NEW_CONTRACT]" | 
					
						
							| 
									
										
										
										
											2015-01-26 10:57:23 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 	// we can ignore the error here because From is | 
					
						
							|  |  |  | 	// verified in ValidateTransaction. | 
					
						
							|  |  |  | 	f, _ := tx.From() | 
					
						
							|  |  |  | 	from := common.Bytes2Hex(f[:4]) | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if glog.V(logger.Debug) { | 
					
						
							|  |  |  | 		glog.Infof("(t) %x => %s (%v) %x\n", from, toname, tx.Value, tx.Hash()) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 23:54:07 +01:00
										 |  |  | func (self *TxPool) Size() int { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	return len(self.txs) | 
					
						
							| 
									
										
										
										
											2014-12-04 23:54:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-05-07 17:27:17 +02:00
										 |  |  | // GetTransaction allows you to check the pending and queued transaction in the | 
					
						
							|  |  |  | // transaction pool. | 
					
						
							|  |  |  | // It has two stategies, first check the pool (map) then check the queue | 
					
						
							|  |  |  | func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { | 
					
						
							|  |  |  | 	// check the txs first | 
					
						
							|  |  |  | 	if tx, ok := tp.txs[hash]; ok { | 
					
						
							|  |  |  | 		return tx | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check queue | 
					
						
							|  |  |  | 	for _, txs := range tp.queue { | 
					
						
							|  |  |  | 		for _, tx := range txs { | 
					
						
							|  |  |  | 			if tx.Hash() == hash { | 
					
						
							|  |  |  | 				return tx | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | func (self *TxPool) GetTransactions() (txs types.Transactions) { | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 	self.mu.RLock() | 
					
						
							|  |  |  | 	defer self.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	txs = make(types.Transactions, self.Size()) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	i := 0 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	for _, tx := range self.txs { | 
					
						
							|  |  |  | 		txs[i] = tx | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		i++ | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	return | 
					
						
							| 
									
										
										
										
											2014-03-28 11:20:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-23 10:51:13 +02:00
										 |  |  | func (self *TxPool) GetQueuedTransactions() types.Transactions { | 
					
						
							|  |  |  | 	self.mu.RLock() | 
					
						
							|  |  |  | 	defer self.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var txs types.Transactions | 
					
						
							|  |  |  | 	for _, ts := range self.queue { | 
					
						
							|  |  |  | 		txs = append(txs, ts...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return txs | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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() | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-02-19 22:33:22 +01:00
										 |  |  | func (pool *TxPool) Flush() { | 
					
						
							| 
									
										
										
										
											2015-03-17 11:59:26 +01:00
										 |  |  | 	pool.txs = make(map[common.Hash]*types.Transaction) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) Stop() { | 
					
						
							|  |  |  | 	pool.Flush() | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	close(pool.quit) | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	glog.V(logger.Info).Infoln("TX Pool stopped") | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 23:20:27 +02:00
										 |  |  | func (self *TxPool) queueTx(tx *types.Transaction) { | 
					
						
							|  |  |  | 	from, _ := tx.From() | 
					
						
							|  |  |  | 	self.queue[from] = append(self.queue[from], tx) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) addTx(tx *types.Transaction) { | 
					
						
							|  |  |  | 	if _, ok := pool.txs[tx.Hash()]; !ok { | 
					
						
							|  |  |  | 		pool.txs[tx.Hash()] = tx | 
					
						
							| 
									
										
										
										
											2015-04-22 17:56:06 +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-04-21 23:20:27 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | // check queue will attempt to insert | 
					
						
							|  |  |  | func (pool *TxPool) checkQueue() { | 
					
						
							|  |  |  | 	pool.mu.Lock() | 
					
						
							|  |  |  | 	defer pool.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 	statedb := pool.currentState() | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 	for address, txs := range pool.queue { | 
					
						
							|  |  |  | 		sort.Sort(types.TxByNonce{txs}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var ( | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 			nonce = statedb.GetNonce(address) | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 			start int | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		// Clean up the transactions first and determine the start of the nonces | 
					
						
							|  |  |  | 		for _, tx := range txs { | 
					
						
							|  |  |  | 			if tx.Nonce() >= nonce { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			start++ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		pool.queue[address] = txs[start:] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// expected nonce | 
					
						
							|  |  |  | 		enonce := nonce | 
					
						
							|  |  |  | 		for _, tx := range pool.queue[address] { | 
					
						
							|  |  |  | 			// If the expected nonce does not match up with the next one | 
					
						
							|  |  |  | 			// (i.e. a nonce gap), we stop the loop | 
					
						
							|  |  |  | 			if enonce != tx.Nonce() { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			enonce++ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-21 23:20:27 +02:00
										 |  |  | 			pool.addTx(tx) | 
					
						
							| 
									
										
										
										
											2015-04-21 22:01:04 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// delete the entire queue entry if it's empty. There's no need to keep it | 
					
						
							|  |  |  | 		if len(pool.queue[address]) == 0 { | 
					
						
							|  |  |  | 			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 | 
					
						
							|  |  |  | 	delete(pool.txs, hash) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// delete from queue | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	for address, txs := range pool.queue { | 
					
						
							|  |  |  | 		for i, tx := range txs { | 
					
						
							|  |  |  | 			if tx.Hash() == hash { | 
					
						
							|  |  |  | 				if len(txs) == 1 { | 
					
						
							|  |  |  | 					// if only one tx, remove entire address entry | 
					
						
							|  |  |  | 					delete(pool.queue, address) | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					pool.queue[address][len(txs)-1], pool.queue[address] = nil, append(txs[:i], txs[i+1:]...) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break out | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | func (pool *TxPool) validatePool() { | 
					
						
							|  |  |  | 	pool.mu.Lock() | 
					
						
							|  |  |  | 	defer pool.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for hash, tx := range pool.txs { | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 		if err := pool.ValidateTransaction(tx); err != nil { | 
					
						
							|  |  |  | 			if glog.V(logger.Info) { | 
					
						
							|  |  |  | 				glog.Infof("removed tx (%x) from pool: %v\n", hash[:4], err) | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 00:20:59 +02:00
										 |  |  | 			pool.removeTx(hash) | 
					
						
							| 
									
										
										
										
											2015-04-23 11:09:58 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |