Merge pull request #1997 from zsfelfoldi/gasprice2
core: tx pool skip price validation for "owned" transactions
This commit is contained in:
		
						commit
						82a024d425
					
				| @ -22,6 +22,7 @@ import ( | |||||||
| 	"math/big" | 	"math/big" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/ethereum/go-ethereum/common" | 	"github.com/ethereum/go-ethereum/common" | ||||||
| 	"github.com/ethereum/go-ethereum/core/state" | 	"github.com/ethereum/go-ethereum/core/state" | ||||||
| @ -65,10 +66,10 @@ type TxPool struct { | |||||||
| 	minGasPrice  *big.Int | 	minGasPrice  *big.Int | ||||||
| 	eventMux     *event.TypeMux | 	eventMux     *event.TypeMux | ||||||
| 	events       event.Subscription | 	events       event.Subscription | ||||||
| 
 | 	localTx      *txSet | ||||||
| 	mu      sync.RWMutex | 	mu           sync.RWMutex | ||||||
| 	pending map[common.Hash]*types.Transaction // processable transactions
 | 	pending      map[common.Hash]*types.Transaction // processable transactions
 | ||||||
| 	queue   map[common.Address]map[common.Hash]*types.Transaction | 	queue        map[common.Address]map[common.Hash]*types.Transaction | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool { | func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool { | ||||||
| @ -81,6 +82,7 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func( | |||||||
| 		gasLimit:     gasLimitFn, | 		gasLimit:     gasLimitFn, | ||||||
| 		minGasPrice:  new(big.Int), | 		minGasPrice:  new(big.Int), | ||||||
| 		pendingState: nil, | 		pendingState: nil, | ||||||
|  | 		localTx:      newTxSet(), | ||||||
| 		events:       eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}), | 		events:       eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}), | ||||||
| 	} | 	} | ||||||
| 	go pool.eventLoop() | 	go pool.eventLoop() | ||||||
| @ -168,6 +170,14 @@ func (pool *TxPool) Stats() (pending int, queued int) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // SetLocal marks a transaction as local, skipping gas price
 | ||||||
|  | //  check against local miner minimum in the future
 | ||||||
|  | func (pool *TxPool) SetLocal(tx *types.Transaction) { | ||||||
|  | 	pool.mu.Lock() | ||||||
|  | 	defer pool.mu.Unlock() | ||||||
|  | 	pool.localTx.add(tx.Hash()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // validateTx checks whether a transaction is valid according
 | // validateTx checks whether a transaction is valid according
 | ||||||
| // to the consensus rules.
 | // to the consensus rules.
 | ||||||
| func (pool *TxPool) validateTx(tx *types.Transaction) error { | func (pool *TxPool) validateTx(tx *types.Transaction) error { | ||||||
| @ -177,8 +187,9 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error { | |||||||
| 		err  error | 		err  error | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
|  | 	local := pool.localTx.contains(tx.Hash()) | ||||||
| 	// Drop transactions under our own minimal accepted gas price
 | 	// Drop transactions under our own minimal accepted gas price
 | ||||||
| 	if pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { | 	if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 { | ||||||
| 		return ErrCheap | 		return ErrCheap | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -489,3 +500,49 @@ type txQueueEntry struct { | |||||||
| func (q txQueue) Len() int           { return len(q) } | 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) Swap(i, j int)      { q[i], q[j] = q[j], q[i] } | ||||||
| func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() } | func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() } | ||||||
|  | 
 | ||||||
|  | // txSet represents a set of transaction hashes in which entries
 | ||||||
|  | //  are automatically dropped after txSetDuration time
 | ||||||
|  | type txSet struct { | ||||||
|  | 	txMap          map[common.Hash]struct{} | ||||||
|  | 	txOrd          map[uint64]txOrdType | ||||||
|  | 	addPtr, delPtr uint64 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const txSetDuration = time.Hour * 2 | ||||||
|  | 
 | ||||||
|  | // txOrdType represents an entry in the time-ordered list of transaction hashes
 | ||||||
|  | type txOrdType struct { | ||||||
|  | 	hash common.Hash | ||||||
|  | 	time time.Time | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // newTxSet creates a new transaction set
 | ||||||
|  | func newTxSet() *txSet { | ||||||
|  | 	return &txSet{ | ||||||
|  | 		txMap: make(map[common.Hash]struct{}), | ||||||
|  | 		txOrd: make(map[uint64]txOrdType), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // contains returns true if the set contains the given transaction hash
 | ||||||
|  | // (not thread safe, should be called from a locked environment)
 | ||||||
|  | func (self *txSet) contains(hash common.Hash) bool { | ||||||
|  | 	_, ok := self.txMap[hash] | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // add adds a transaction hash to the set, then removes entries older than txSetDuration
 | ||||||
|  | // (not thread safe, should be called from a locked environment)
 | ||||||
|  | func (self *txSet) add(hash common.Hash) { | ||||||
|  | 	self.txMap[hash] = struct{}{} | ||||||
|  | 	now := time.Now() | ||||||
|  | 	self.txOrd[self.addPtr] = txOrdType{hash: hash, time: now} | ||||||
|  | 	self.addPtr++ | ||||||
|  | 	delBefore := now.Add(-txSetDuration) | ||||||
|  | 	for self.delPtr < self.addPtr && self.txOrd[self.delPtr].time.Before(delBefore) { | ||||||
|  | 		delete(self.txMap, self.txOrd[self.delPtr].hash) | ||||||
|  | 		delete(self.txOrd, self.delPtr) | ||||||
|  | 		self.delPtr++ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -72,6 +72,17 @@ func TestInvalidTransactions(t *testing.T) { | |||||||
| 	if err := pool.Add(tx); err != ErrNonce { | 	if err := pool.Add(tx); err != ErrNonce { | ||||||
| 		t.Error("expected", ErrNonce) | 		t.Error("expected", ErrNonce) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	tx = transaction(1, big.NewInt(100000), key) | ||||||
|  | 	pool.minGasPrice = big.NewInt(1000) | ||||||
|  | 	if err := pool.Add(tx); err != ErrCheap { | ||||||
|  | 		t.Error("expected", ErrCheap, "got", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pool.SetLocal(tx) | ||||||
|  | 	if err := pool.Add(tx); err != nil { | ||||||
|  | 		t.Error("expected", nil, "got", err) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestTransactionQueue(t *testing.T) { | func TestTransactionQueue(t *testing.T) { | ||||||
|  | |||||||
| @ -926,6 +926,7 @@ func (s *PublicTransactionPoolAPI) SendTransaction(args SendTxArgs) (common.Hash | |||||||
| 		return common.Hash{}, err | 		return common.Hash{}, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	s.txPool.SetLocal(signedTx) | ||||||
| 	if err := s.txPool.Add(signedTx); err != nil { | 	if err := s.txPool.Add(signedTx); err != nil { | ||||||
| 		return common.Hash{}, nil | 		return common.Hash{}, nil | ||||||
| 	} | 	} | ||||||
| @ -948,6 +949,7 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(encodedTx string) (string, | |||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	s.txPool.SetLocal(tx) | ||||||
| 	if err := s.txPool.Add(tx); err != nil { | 	if err := s.txPool.Add(tx); err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1044,6 +1044,7 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  | 	self.EthereumService().TxPool().SetLocal(signed) | ||||||
| 	if err = self.EthereumService().TxPool().Add(signed); err != nil { | 	if err = self.EthereumService().TxPool().Add(signed); err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user