| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2015-01-02 22:19:58 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 12:56:05 +01:00
										 |  |  | var txplogger = logger.NewLogger("TXP") | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | type TxMsg struct { | 
					
						
							|  |  |  | 	Tx *types.Transaction | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 	// 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 | 
					
						
							|  |  |  | 	// The actual pool | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 	//pool *list.List | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	txs map[string]*types.Transaction | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 01:57:04 +01:00
										 |  |  | 	SecondaryProcessor TxProcessor | 
					
						
							| 
									
										
										
										
											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-01-02 12:26:55 +01:00
										 |  |  | func NewTxPool(eventMux *event.TypeMux) *TxPool { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	return &TxPool{ | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 		txs:       make(map[string]*types.Transaction), | 
					
						
							| 
									
										
										
										
											2015-01-02 12:26:55 +01:00
										 |  |  | 		queueChan: make(chan *types.Transaction, txPoolQueueSize), | 
					
						
							|  |  |  | 		quit:      make(chan bool), | 
					
						
							|  |  |  | 		eventMux:  eventMux, | 
					
						
							| 
									
										
										
										
											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-01-05 17:10:42 +01:00
										 |  |  | 	hash := tx.Hash() | 
					
						
							|  |  |  | 	if pool.txs[string(hash)] != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("Known transaction (%x)", hash[0:4]) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	if len(tx.To()) != 0 && len(tx.To()) != 20 { | 
					
						
							|  |  |  | 		return fmt.Errorf("Invalid recipient. len = %d", len(tx.To())) | 
					
						
							| 
									
										
										
										
											2014-12-02 00:14:34 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-02 12:26:55 +01:00
										 |  |  | 	/* XXX this kind of validation needs to happen elsewhere in the gui when sending txs. | 
					
						
							|  |  |  | 	   Other clients should do their own validation. Value transfer could throw error | 
					
						
							|  |  |  | 	   but doesn't necessarily invalidate the tx. Gas can still be payed for and miner | 
					
						
							|  |  |  | 	   can still be rewarded for their inclusion and processing. | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Get the sender | 
					
						
							| 
									
										
										
										
											2014-12-19 00:33:05 +01:00
										 |  |  | 	senderAddr := tx.From() | 
					
						
							| 
									
										
										
										
											2014-11-28 19:39:20 -05:00
										 |  |  | 	if senderAddr == nil { | 
					
						
							| 
									
										
										
										
											2014-12-19 00:33:05 +01:00
										 |  |  | 		return fmt.Errorf("invalid sender") | 
					
						
							| 
									
										
										
										
											2014-11-28 19:39:20 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 	sender := pool.stateQuery.GetAccount(senderAddr) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	totAmount := new(big.Int).Set(tx.Value()) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Make sure there's enough in the sender's account. Having insufficient | 
					
						
							|  |  |  | 	// funds won't invalidate this transaction but simple ignores it. | 
					
						
							| 
									
										
										
										
											2014-10-23 01:01:26 +02:00
										 |  |  | 	if sender.Balance().Cmp(totAmount) < 0 { | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 		return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From()) | 
					
						
							| 
									
										
										
										
											2014-06-10 15:02:41 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-02 12:24:36 +01:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2014-06-10 15:02:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | func (self *TxPool) addTx(tx *types.Transaction) { | 
					
						
							|  |  |  | 	self.txs[string(tx.Hash())] = tx | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | func (self *TxPool) Add(tx *types.Transaction) error { | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 	err := self.ValidateTransaction(tx) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	self.addTx(tx) | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 22:19:58 +01:00
										 |  |  | 	var to string | 
					
						
							|  |  |  | 	if len(tx.To()) > 0 { | 
					
						
							|  |  |  | 		to = ethutil.Bytes2Hex(tx.To()[:4]) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		to = "[NEW_CONTRACT]" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	txplogger.Debugf("(t) %x => %s (%v) %x\n", tx.From()[:4], to, tx.Value, tx.Hash()) | 
					
						
							| 
									
										
										
										
											2014-12-01 20:18:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Notify the subscribers | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	go self.eventMux.Post(TxPreEvent{tx}) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | func (self *TxPool) AddTransactions(txs []*types.Transaction) { | 
					
						
							|  |  |  | 	for _, tx := range txs { | 
					
						
							|  |  |  | 		if err := self.Add(tx); err != nil { | 
					
						
							|  |  |  | 			txplogger.Infoln(err) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			txplogger.Infof("tx %x\n", tx.Hash()[0:4]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | func (self *TxPool) GetTransactions() (txs types.Transactions) { | 
					
						
							|  |  |  | 	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-01-02 12:09:38 +01:00
										 |  |  | func (pool *TxPool) RemoveInvalid(query StateQuery) { | 
					
						
							|  |  |  | 	var removedTxs types.Transactions | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	for _, tx := range pool.txs { | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 		sender := query.GetAccount(tx.From()) | 
					
						
							| 
									
										
										
										
											2014-05-14 16:29:34 +02:00
										 |  |  | 		err := pool.ValidateTransaction(tx) | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 		if err != nil || sender.Nonce >= tx.Nonce() { | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 			removedTxs = append(removedTxs, tx) | 
					
						
							| 
									
										
										
										
											2014-05-14 16:29:34 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-02 12:09:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pool.RemoveSet(removedTxs) | 
					
						
							| 
									
										
										
										
											2014-05-14 16:29:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | func (self *TxPool) RemoveSet(txs types.Transactions) { | 
					
						
							| 
									
										
										
										
											2014-10-27 16:52:58 +01:00
										 |  |  | 	for _, tx := range txs { | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 		delete(self.txs, string(tx.Hash())) | 
					
						
							| 
									
										
										
										
											2014-10-27 16:52:58 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-18 16:58:22 +01:00
										 |  |  | func (pool *TxPool) Flush() []*types.Transaction { | 
					
						
							| 
									
										
										
										
											2014-12-14 18:15:48 +00:00
										 |  |  | 	txList := pool.GetTransactions() | 
					
						
							| 
									
										
										
										
											2015-01-05 17:10:42 +01:00
										 |  |  | 	pool.txs = make(map[string]*types.Transaction) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return txList | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) Start() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (pool *TxPool) Stop() { | 
					
						
							|  |  |  | 	pool.Flush() | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-23 12:54:10 +01:00
										 |  |  | 	txplogger.Infoln("Stopped") | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } |