core: tx pool skip price validation for "owned" transactions
This commit is contained in:
parent
b9aedeab0b
commit
975c591261
|
@ -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