github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/tx_pool.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  	"sort"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/ethereumproject/go-ethereum/common"
    28  	"github.com/ethereumproject/go-ethereum/core/state"
    29  	"github.com/ethereumproject/go-ethereum/core/types"
    30  	"github.com/ethereumproject/go-ethereum/event"
    31  	"github.com/ethereumproject/go-ethereum/logger"
    32  	"github.com/ethereumproject/go-ethereum/logger/glog"
    33  )
    34  
    35  var (
    36  	// Transaction Pool Errors
    37  	ErrInvalidSender      = errors.New("Invalid sender")
    38  	ErrNonce              = errors.New("Nonce too low")
    39  	ErrCheap              = errors.New("Gas price too low for acceptance")
    40  	ErrBalance            = errors.New("Insufficient balance")
    41  	ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
    42  	ErrInsufficientFunds  = errors.New("Insufficient funds for gas * price + value")
    43  	ErrIntrinsicGas       = errors.New("Intrinsic gas too low")
    44  	ErrGasLimit           = errors.New("Exceeds block gas limit")
    45  	ErrNegativeValue      = errors.New("Negative value")
    46  )
    47  
    48  const (
    49  	maxQueued = 64 // max limit of queued txs per address
    50  )
    51  
    52  type stateFn func() (*state.StateDB, error)
    53  
    54  // TxPool contains all currently known transactions. Transactions
    55  // enter the pool when they are received from the network or submitted
    56  // locally. They exit the pool when they are included in the blockchain.
    57  //
    58  // The pool separates processable transactions (which can be applied to the
    59  // current state) and future transactions. Transactions move between those
    60  // two states over time as they are received and processed.
    61  type TxPool struct {
    62  	config       *ChainConfig
    63  	signer       types.Signer
    64  	currentState stateFn // The state function which will allow us to do some pre checks
    65  	pendingState *state.ManagedState
    66  	gasLimit     func() *big.Int // The current gas limit function callback
    67  	minGasPrice  *big.Int
    68  	eventMux     *event.TypeMux
    69  	events       event.Subscription
    70  	localTx      *txSet
    71  	mu           sync.RWMutex
    72  	pending      map[common.Hash]*types.Transaction // processable transactions
    73  	queue        map[common.Address]map[common.Hash]*types.Transaction
    74  
    75  	wg sync.WaitGroup // for shutdown sync
    76  
    77  	homestead bool
    78  }
    79  
    80  func NewTxPool(config *ChainConfig, eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func() *big.Int) *TxPool {
    81  	pool := &TxPool{
    82  		config:       config,
    83  		signer:       types.NewChainIdSigner(config.GetChainID()),
    84  		pending:      make(map[common.Hash]*types.Transaction),
    85  		queue:        make(map[common.Address]map[common.Hash]*types.Transaction),
    86  		eventMux:     eventMux,
    87  		currentState: currentStateFn,
    88  		gasLimit:     gasLimitFn,
    89  		minGasPrice:  new(big.Int),
    90  		pendingState: nil,
    91  		localTx:      newTxSet(),
    92  		events:       eventMux.Subscribe(ChainHeadEvent{}, GasPriceChanged{}, RemovedTransactionEvent{}),
    93  	}
    94  
    95  	pool.wg.Add(1)
    96  	go pool.eventLoop()
    97  
    98  	return pool
    99  }
   100  
   101  func (pool *TxPool) eventLoop() {
   102  	defer pool.wg.Done()
   103  
   104  	// Track chain events. When a chain events occurs (new chain canon block)
   105  	// we need to know the new state. The new state will help us determine
   106  	// the nonces in the managed state
   107  	for ev := range pool.events.Chan() {
   108  		switch ev := ev.Data.(type) {
   109  		case ChainHeadEvent:
   110  			pool.mu.Lock()
   111  			if ev.Block != nil && pool.config.IsHomestead(ev.Block.Number()) {
   112  				pool.homestead = true
   113  			}
   114  
   115  			pool.resetState()
   116  			pool.mu.Unlock()
   117  		case GasPriceChanged:
   118  			pool.mu.Lock()
   119  			pool.minGasPrice = ev.Price
   120  			pool.mu.Unlock()
   121  		case RemovedTransactionEvent:
   122  			pool.AddTransactions(ev.Txs)
   123  		}
   124  	}
   125  }
   126  
   127  func (pool *TxPool) resetState() {
   128  	currentState, err := pool.currentState()
   129  	if err != nil {
   130  		glog.V(logger.Info).Infof("failed to get current state: %v", err)
   131  		return
   132  	}
   133  	managedState := state.ManageState(currentState)
   134  	if err != nil {
   135  		glog.V(logger.Info).Infof("failed to get managed state: %v", err)
   136  		return
   137  	}
   138  	pool.pendingState = managedState
   139  
   140  	// validate the pool of pending transactions, this will remove
   141  	// any transactions that have been included in the block or
   142  	// have been invalidated because of another transaction (e.g.
   143  	// higher gas price)
   144  	pool.validatePool()
   145  
   146  	// Loop over the pending transactions and base the nonce of the new
   147  	// pending transaction set.
   148  	for _, tx := range pool.pending {
   149  		if addr, err := tx.From(); err == nil {
   150  			// Set the nonce. Transaction nonce can never be lower
   151  			// than the state nonce; validatePool took care of that.
   152  			if pool.pendingState.GetNonce(addr) <= tx.Nonce() {
   153  				pool.pendingState.SetNonce(addr, tx.Nonce()+1)
   154  			}
   155  		}
   156  	}
   157  	// Check the queue and move transactions over to the pending if possible
   158  	// or remove those that have become invalid
   159  	pool.checkQueue()
   160  }
   161  
   162  func (pool *TxPool) Stop() {
   163  	pool.events.Unsubscribe()
   164  	pool.wg.Wait()
   165  	glog.V(logger.Info).Infoln("Transaction pool stopped")
   166  }
   167  
   168  func (pool *TxPool) State() *state.ManagedState {
   169  	pool.mu.RLock()
   170  	defer pool.mu.RUnlock()
   171  
   172  	return pool.pendingState
   173  }
   174  
   175  func (pool *TxPool) Stats() (pending int, queued int) {
   176  	pool.mu.RLock()
   177  	defer pool.mu.RUnlock()
   178  
   179  	pending = len(pool.pending)
   180  	for _, txs := range pool.queue {
   181  		queued += len(txs)
   182  	}
   183  	return
   184  }
   185  
   186  // Content retrieves the data content of the transaction pool, returning all the
   187  // pending as well as queued transactions, grouped by account and nonce.
   188  func (pool *TxPool) Content() (map[common.Address]map[uint64][]*types.Transaction, map[common.Address]map[uint64][]*types.Transaction) {
   189  	pool.mu.RLock()
   190  	defer pool.mu.RUnlock()
   191  
   192  	// Retrieve all the pending transactions and sort by account and by nonce
   193  	pending := make(map[common.Address]map[uint64][]*types.Transaction)
   194  	for _, tx := range pool.pending {
   195  		account, _ := tx.From()
   196  
   197  		owned, ok := pending[account]
   198  		if !ok {
   199  			owned = make(map[uint64][]*types.Transaction)
   200  			pending[account] = owned
   201  		}
   202  		owned[tx.Nonce()] = append(owned[tx.Nonce()], tx)
   203  	}
   204  	// Retrieve all the queued transactions and sort by account and by nonce
   205  	queued := make(map[common.Address]map[uint64][]*types.Transaction)
   206  	for account, txs := range pool.queue {
   207  		owned := make(map[uint64][]*types.Transaction)
   208  		for _, tx := range txs {
   209  			owned[tx.Nonce()] = append(owned[tx.Nonce()], tx)
   210  		}
   211  		queued[account] = owned
   212  	}
   213  	return pending, queued
   214  }
   215  
   216  // SetLocal marks a transaction as local, skipping gas price
   217  //  check against local miner minimum in the future
   218  func (pool *TxPool) SetLocal(tx *types.Transaction) {
   219  	pool.mu.Lock()
   220  	defer pool.mu.Unlock()
   221  	pool.localTx.add(tx.Hash())
   222  }
   223  
   224  // validateTx checks whether a transaction is valid according
   225  // to the consensus rules.
   226  func (pool *TxPool) validateTx(tx *types.Transaction) (e error) {
   227  	local := pool.localTx.contains(tx.Hash())
   228  	defer func() {
   229  		mlogTxPoolValidateTx.AssignDetails(
   230  			tx.Hash().Hex(),
   231  			tx.Size(),
   232  			common.StorageSize(len(tx.Data())),
   233  			tx.Nonce(),
   234  			tx.Gas(),
   235  			tx.GasPrice(),
   236  			e == nil,
   237  			e,
   238  		).Send(mlogTxPool)
   239  	}()
   240  	// Drop transactions under our own minimal accepted gas price
   241  	if !local && pool.minGasPrice.Cmp(tx.GasPrice()) > 0 {
   242  		e = ErrCheap
   243  		return
   244  	}
   245  
   246  	currentState, err := pool.currentState()
   247  	if err != nil {
   248  		e = err
   249  		return
   250  	}
   251  
   252  	from, err := types.Sender(pool.signer, tx)
   253  	if err != nil {
   254  		e = ErrInvalidSender
   255  		return
   256  	}
   257  
   258  	// Make sure the account exist. Non existent accounts
   259  	// haven't got funds and well therefor never pass.
   260  	if !currentState.Exist(from) {
   261  		e = ErrNonExistentAccount
   262  		return
   263  	}
   264  
   265  	// Last but not least check for nonce errors
   266  	if currentState.GetNonce(from) > tx.Nonce() {
   267  		e = ErrNonce
   268  		return
   269  	}
   270  
   271  	// Check the transaction doesn't exceed the current
   272  	// block limit gas.
   273  	if pool.gasLimit().Cmp(tx.Gas()) < 0 {
   274  		e = ErrGasLimit
   275  		return
   276  	}
   277  
   278  	// Transactions can't be negative. This may never happen
   279  	// using RLP decoded transactions but may occur if you create
   280  	// a transaction using the RPC for example.
   281  	if tx.Value().Sign() < 0 {
   282  		e = ErrNegativeValue
   283  		return
   284  	}
   285  
   286  	// Transactor should have enough funds to cover the costs
   287  	// cost == V + GP * GL
   288  	if currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
   289  		e = ErrInsufficientFunds
   290  		return
   291  	}
   292  
   293  	intrGas := IntrinsicGas(tx.Data(), MessageCreatesContract(tx), pool.homestead)
   294  	if tx.Gas().Cmp(intrGas) < 0 {
   295  		e = ErrIntrinsicGas
   296  		return
   297  	}
   298  	return // e=nil
   299  }
   300  
   301  // validate and queue transactions.
   302  func (self *TxPool) add(tx *types.Transaction) error {
   303  	hash := tx.Hash()
   304  
   305  	if self.pending[hash] != nil {
   306  		return fmt.Errorf("Known transaction (%x)", hash[:4])
   307  	}
   308  	err := self.validateTx(tx)
   309  	if err != nil {
   310  		return err
   311  	}
   312  	self.queueTx(hash, tx)
   313  
   314  	var toName, toLogName string
   315  	if to := tx.To(); to != nil {
   316  		toName = common.Bytes2Hex(to[:4])
   317  		toLogName = tx.To().Hex()
   318  	} else {
   319  		toName = "[NEW_CONTRACT]"
   320  		toLogName = "[NEW_CONTRACT]"
   321  	}
   322  	// we can ignore the error here because From is
   323  	// verified in ValidateTransaction.
   324  	f, _ := types.Sender(self.signer, tx)
   325  	from := common.Bytes2Hex(f[:4])
   326  
   327  	if logger.MlogEnabled() {
   328  		mlogTxPoolAddTx.AssignDetails(
   329  			f.Hex(),
   330  			toLogName,
   331  			tx.Value,
   332  			hash.Hex(),
   333  		).Send(mlogTxPool)
   334  	}
   335  	if glog.V(logger.Debug) {
   336  		glog.Infof("(t) %x => %s (%v) %x\n", from, toName, tx.Value(), hash)
   337  	}
   338  
   339  	return nil
   340  }
   341  
   342  // queueTx will queue an unknown transaction
   343  func (self *TxPool) queueTx(hash common.Hash, tx *types.Transaction) {
   344  	from, _ := types.Sender(self.signer, tx) // already validated
   345  	if self.queue[from] == nil {
   346  		self.queue[from] = make(map[common.Hash]*types.Transaction)
   347  	}
   348  	self.queue[from][hash] = tx
   349  }
   350  
   351  // addTx will add a transaction to the pending (processable queue) list of transactions
   352  func (pool *TxPool) addTx(hash common.Hash, addr common.Address, tx *types.Transaction) {
   353  	// init delayed since tx pool could have been started before any state sync
   354  	if pool.pendingState == nil {
   355  		pool.resetState()
   356  	}
   357  
   358  	if _, ok := pool.pending[hash]; !ok {
   359  		pool.pending[hash] = tx
   360  
   361  		// Increment the nonce on the pending state. This can only happen if
   362  		// the nonce is +1 to the previous one.
   363  		pool.pendingState.SetNonce(addr, tx.Nonce()+1)
   364  		// Notify the subscribers. This event is posted in a goroutine
   365  		// because it's possible that somewhere during the post "Remove transaction"
   366  		// gets called which will then wait for the global tx pool lock and deadlock.
   367  		go pool.eventMux.Post(TxPreEvent{tx})
   368  	}
   369  }
   370  
   371  // Add queues a single transaction in the pool if it is valid.
   372  func (self *TxPool) Add(tx *types.Transaction) error {
   373  	self.mu.Lock()
   374  	defer self.mu.Unlock()
   375  
   376  	if err := self.add(tx); err != nil {
   377  		return err
   378  	}
   379  	self.checkQueue()
   380  	return nil
   381  }
   382  
   383  // AddTransactions attempts to queue all valid transactions in txs.
   384  func (self *TxPool) AddTransactions(txs []*types.Transaction) {
   385  	self.mu.Lock()
   386  	defer self.mu.Unlock()
   387  
   388  	for _, tx := range txs {
   389  		if err := self.add(tx); err != nil {
   390  			glog.V(logger.Debug).Infoln("tx error:", err)
   391  		} else {
   392  			h := tx.Hash()
   393  			glog.V(logger.Debug).Infof("tx %x\n", h[:4])
   394  		}
   395  	}
   396  
   397  	// check and validate the queue
   398  	self.checkQueue()
   399  }
   400  
   401  // GetTransaction returns a transaction if it is contained in the pool
   402  // and nil otherwise.
   403  func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction {
   404  	tp.mu.RLock()
   405  	defer tp.mu.RUnlock()
   406  
   407  	// check the txs first
   408  	if tx, ok := tp.pending[hash]; ok {
   409  		return tx
   410  	}
   411  	// check queue
   412  	for _, txs := range tp.queue {
   413  		if tx, ok := txs[hash]; ok {
   414  			return tx
   415  		}
   416  	}
   417  	return nil
   418  }
   419  
   420  // GetTransactions returns all currently processable transactions.
   421  // The returned slice may be modified by the caller.
   422  func (self *TxPool) GetTransactions() (txs types.Transactions) {
   423  	self.mu.Lock()
   424  	defer self.mu.Unlock()
   425  
   426  	// check queue first
   427  	self.checkQueue()
   428  	// invalidate any txs
   429  	self.validatePool()
   430  
   431  	txs = make(types.Transactions, len(self.pending))
   432  	i := 0
   433  	for _, tx := range self.pending {
   434  		txs[i] = tx
   435  		i++
   436  	}
   437  	return txs
   438  }
   439  
   440  // GetQueuedTransactions returns all non-processable transactions.
   441  func (self *TxPool) GetQueuedTransactions() types.Transactions {
   442  	self.mu.RLock()
   443  	defer self.mu.RUnlock()
   444  
   445  	var ret types.Transactions
   446  	for _, txs := range self.queue {
   447  		for _, tx := range txs {
   448  			ret = append(ret, tx)
   449  		}
   450  	}
   451  	sort.Sort(types.TxByNonce(ret))
   452  	return ret
   453  }
   454  
   455  // RemoveTransactions removes all given transactions from the pool.
   456  func (self *TxPool) RemoveTransactions(txs types.Transactions) {
   457  	self.mu.Lock()
   458  	defer self.mu.Unlock()
   459  	for _, tx := range txs {
   460  		self.removeTx(tx.Hash())
   461  	}
   462  }
   463  
   464  // RemoveTx removes the transaction with the given hash from the pool.
   465  func (pool *TxPool) RemoveTx(hash common.Hash) {
   466  	pool.mu.Lock()
   467  	defer pool.mu.Unlock()
   468  	pool.removeTx(hash)
   469  }
   470  
   471  func (pool *TxPool) removeTx(hash common.Hash) {
   472  	// delete from pending pool
   473  	delete(pool.pending, hash)
   474  	// delete from queue
   475  	for address, txs := range pool.queue {
   476  		if _, ok := txs[hash]; ok {
   477  			if len(txs) == 1 {
   478  				// if only one tx, remove entire address entry.
   479  				delete(pool.queue, address)
   480  			} else {
   481  				delete(txs, hash)
   482  			}
   483  			break
   484  		}
   485  	}
   486  }
   487  
   488  // checkQueue moves transactions that have become processable to main pool.
   489  func (pool *TxPool) checkQueue() {
   490  	// init delayed since tx pool could have been started before any state sync
   491  	if pool.pendingState == nil {
   492  		pool.resetState()
   493  	}
   494  
   495  	var promote txQueue
   496  	for address, txs := range pool.queue {
   497  		currentState, err := pool.currentState()
   498  		if err != nil {
   499  			glog.Errorf("could not get current state: %v", err)
   500  			return
   501  		}
   502  		balance := currentState.GetBalance(address)
   503  
   504  		var (
   505  			guessedNonce = pool.pendingState.GetNonce(address) // nonce currently kept by the tx pool (pending state)
   506  			trueNonce    = currentState.GetNonce(address)      // nonce known by the last state
   507  		)
   508  		promote = promote[:0]
   509  		for hash, tx := range txs {
   510  			// Drop processed or out of fund transactions
   511  			if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 {
   512  				if glog.V(logger.Core) {
   513  					glog.Infof("removed tx (%v) from pool queue: low tx nonce or out of funds\n", tx)
   514  				}
   515  				delete(txs, hash)
   516  				continue
   517  			}
   518  			// Collect the remaining transactions for the next pass.
   519  			promote = append(promote, txQueueEntry{hash, address, tx})
   520  		}
   521  		// Find the next consecutive nonce range starting at the current account nonce,
   522  		// pushing the guessed nonce forward if we add consecutive transactions.
   523  		sort.Sort(promote)
   524  		for i, entry := range promote {
   525  			// If we reached a gap in the nonces, enforce transaction limit and stop
   526  			if entry.Nonce() > guessedNonce {
   527  				if len(promote)-i > maxQueued {
   528  					if glog.V(logger.Debug) {
   529  						glog.Infof("Queued tx limit exceeded for %s. Tx %s removed\n", common.PP(address[:]), common.PP(entry.hash[:]))
   530  					}
   531  					for _, drop := range promote[i+maxQueued:] {
   532  						delete(txs, drop.hash)
   533  					}
   534  				}
   535  				break
   536  			}
   537  			// Otherwise promote the transaction and move the guess nonce if needed
   538  			pool.addTx(entry.hash, address, entry.Transaction)
   539  			delete(txs, entry.hash)
   540  
   541  			if entry.Nonce() == guessedNonce {
   542  				guessedNonce++
   543  			}
   544  		}
   545  		// Delete the entire queue entry if it became empty.
   546  		if len(txs) == 0 {
   547  			delete(pool.queue, address)
   548  		}
   549  	}
   550  }
   551  
   552  // validatePool removes invalid and processed transactions from the main pool.
   553  // If a transaction is removed for being invalid (e.g. out of funds), all sub-
   554  // sequent (Still valid) transactions are moved back into the future queue. This
   555  // is important to prevent a drained account from DOSing the network with non
   556  // executable transactions.
   557  func (pool *TxPool) validatePool() {
   558  	state, err := pool.currentState()
   559  	if err != nil {
   560  		glog.V(logger.Info).Infof("failed to get current state: %v", err)
   561  		return
   562  	}
   563  	balanceCache := make(map[common.Address]*big.Int)
   564  
   565  	// Clean up the pending pool, accumulating invalid nonces
   566  	gaps := make(map[common.Address]uint64)
   567  
   568  	for hash, tx := range pool.pending {
   569  		sender, _ := tx.From() // err already checked
   570  
   571  		// Perform light nonce and balance validation
   572  		balance := balanceCache[sender]
   573  		if balance == nil {
   574  			balance = state.GetBalance(sender)
   575  			balanceCache[sender] = balance
   576  		}
   577  		if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 {
   578  			// Remove an already past it invalidated transaction
   579  			if glog.V(logger.Core) {
   580  				glog.Infof("removed tx (%v) from pool: low tx nonce or out of funds\n", tx)
   581  			}
   582  			delete(pool.pending, hash)
   583  
   584  			// Track the smallest invalid nonce to postpone subsequent transactions
   585  			if !past {
   586  				if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev {
   587  					gaps[sender] = tx.Nonce()
   588  				}
   589  			}
   590  		}
   591  	}
   592  	// Move all transactions after a gap back to the future queue
   593  	if len(gaps) > 0 {
   594  		for hash, tx := range pool.pending {
   595  			sender, _ := tx.From()
   596  			if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap {
   597  				if glog.V(logger.Core) {
   598  					glog.Infof("postponed tx (%v) due to introduced gap\n", tx)
   599  				}
   600  				pool.queueTx(hash, tx)
   601  				delete(pool.pending, hash)
   602  			}
   603  		}
   604  	}
   605  }
   606  
   607  type txQueue []txQueueEntry
   608  
   609  type txQueueEntry struct {
   610  	hash common.Hash
   611  	addr common.Address
   612  	*types.Transaction
   613  }
   614  
   615  func (q txQueue) Len() int           { return len(q) }
   616  func (q txQueue) Swap(i, j int)      { q[i], q[j] = q[j], q[i] }
   617  func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() }
   618  
   619  // txSet represents a set of transaction hashes in which entries
   620  //  are automatically dropped after txSetDuration time
   621  type txSet struct {
   622  	txMap          map[common.Hash]struct{}
   623  	txOrd          map[uint64]txOrdType
   624  	addPtr, delPtr uint64
   625  }
   626  
   627  const txSetDuration = time.Hour * 2
   628  
   629  // txOrdType represents an entry in the time-ordered list of transaction hashes
   630  type txOrdType struct {
   631  	hash common.Hash
   632  	time time.Time
   633  }
   634  
   635  // newTxSet creates a new transaction set
   636  func newTxSet() *txSet {
   637  	return &txSet{
   638  		txMap: make(map[common.Hash]struct{}),
   639  		txOrd: make(map[uint64]txOrdType),
   640  	}
   641  }
   642  
   643  // contains returns true if the set contains the given transaction hash
   644  // (not thread safe, should be called from a locked environment)
   645  func (self *txSet) contains(hash common.Hash) bool {
   646  	_, ok := self.txMap[hash]
   647  	return ok
   648  }
   649  
   650  // add adds a transaction hash to the set, then removes entries older than txSetDuration
   651  // (not thread safe, should be called from a locked environment)
   652  func (self *txSet) add(hash common.Hash) {
   653  	self.txMap[hash] = struct{}{}
   654  	now := time.Now()
   655  	self.txOrd[self.addPtr] = txOrdType{hash: hash, time: now}
   656  	self.addPtr++
   657  	delBefore := now.Add(-txSetDuration)
   658  	for self.delPtr < self.addPtr && self.txOrd[self.delPtr].time.Before(delBefore) {
   659  		delete(self.txMap, self.txOrd[self.delPtr].hash)
   660  		delete(self.txOrd, self.delPtr)
   661  		self.delPtr++
   662  	}
   663  }