github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/core/tx_pool_test.go (about)

     1  package core
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/big"
     8  	"math/rand"
     9  	"os"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/neatio-net/neatio/chain/core/rawdb"
    14  	"github.com/neatio-net/neatio/chain/core/state"
    15  	"github.com/neatio-net/neatio/chain/core/types"
    16  	"github.com/neatio-net/neatio/params"
    17  	"github.com/neatio-net/neatio/utilities/common"
    18  	"github.com/neatio-net/neatio/utilities/crypto"
    19  	"github.com/neatio-net/neatio/utilities/event"
    20  )
    21  
    22  var testTxPoolConfig TxPoolConfig
    23  
    24  func init() {
    25  	testTxPoolConfig = DefaultTxPoolConfig
    26  	testTxPoolConfig.Journal = ""
    27  }
    28  
    29  type testBlockChain struct {
    30  	statedb       *state.StateDB
    31  	gasLimit      uint64
    32  	chainHeadFeed *event.Feed
    33  }
    34  
    35  func (bc *testBlockChain) CurrentBlock() *types.Block {
    36  	return types.NewBlock(&types.Header{
    37  		GasLimit: bc.gasLimit,
    38  	}, nil, nil, nil)
    39  }
    40  
    41  func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
    42  	return bc.CurrentBlock()
    43  }
    44  
    45  func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {
    46  	return bc.statedb, nil
    47  }
    48  
    49  func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
    50  	return bc.chainHeadFeed.Subscribe(ch)
    51  }
    52  
    53  func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction {
    54  	return pricedTransaction(nonce, gaslimit, big.NewInt(1), key)
    55  }
    56  
    57  func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
    58  	tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
    59  	return tx
    60  }
    61  
    62  func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
    63  	diskdb := rawdb.NewMemoryDatabase()
    64  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb))
    65  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
    66  
    67  	key, _ := crypto.GenerateKey()
    68  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
    69  
    70  	return pool, key
    71  }
    72  
    73  func validateTxPoolInternals(pool *TxPool) error {
    74  	pool.mu.RLock()
    75  	defer pool.mu.RUnlock()
    76  
    77  	pending, queued := pool.stats()
    78  	if total := len(pool.all); total != pending+queued {
    79  		return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued)
    80  	}
    81  	if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued {
    82  		return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued)
    83  	}
    84  	for addr, txs := range pool.pending {
    85  		var last uint64
    86  		for nonce := range txs.txs.items {
    87  			if last < nonce {
    88  				last = nonce
    89  			}
    90  		}
    91  		if nonce := pool.pendingState.GetNonce(addr); nonce != last+1 {
    92  			return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1)
    93  		}
    94  	}
    95  	return nil
    96  }
    97  
    98  func validateEvents(events chan TxPreEvent, count int) error {
    99  	for i := 0; i < count; i++ {
   100  		select {
   101  		case <-events:
   102  		case <-time.After(time.Second):
   103  			return fmt.Errorf("event #%d not fired", i)
   104  		}
   105  	}
   106  	select {
   107  	case tx := <-events:
   108  		return fmt.Errorf("more than %d events fired: %v", count, tx.Tx)
   109  
   110  	case <-time.After(50 * time.Millisecond):
   111  	}
   112  	return nil
   113  }
   114  
   115  func deriveSender(tx *types.Transaction) (common.Address, error) {
   116  	return types.Sender(types.HomesteadSigner{}, tx)
   117  }
   118  
   119  type testChain struct {
   120  	*testBlockChain
   121  	address common.Address
   122  	trigger *bool
   123  }
   124  
   125  func (c *testChain) State() (*state.StateDB, error) {
   126  	stdb := c.statedb
   127  	if *c.trigger {
   128  		db := rawdb.NewMemoryDatabase()
   129  		c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
   130  		c.statedb.SetNonce(c.address, 2)
   131  		c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Nio))
   132  		*c.trigger = false
   133  	}
   134  	return stdb, nil
   135  }
   136  
   137  func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
   138  	t.Parallel()
   139  
   140  	var (
   141  		db         = rawdb.NewMemoryDatabase()
   142  		key, _     = crypto.GenerateKey()
   143  		address    = crypto.PubkeyToAddress(key.PublicKey)
   144  		statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
   145  		trigger    = false
   146  	)
   147  
   148  	statedb.SetBalance(address, new(big.Int).SetUint64(params.Nio))
   149  	blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger}
   150  
   151  	tx0 := transaction(0, 100000, key)
   152  	tx1 := transaction(1, 100000, key)
   153  
   154  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
   155  	defer pool.Stop()
   156  
   157  	nonce := pool.State().GetNonce(address)
   158  	if nonce != 0 {
   159  		t.Fatalf("Invalid nonce, want 0, got %d", nonce)
   160  	}
   161  
   162  	pool.AddRemotes(types.Transactions{tx0, tx1})
   163  
   164  	nonce = pool.State().GetNonce(address)
   165  	if nonce != 2 {
   166  		t.Fatalf("Invalid nonce, want 2, got %d", nonce)
   167  	}
   168  
   169  	// trigger state change in the background
   170  	trigger = true
   171  
   172  	pool.lockedReset(nil, nil)
   173  
   174  	pendingTx, err := pool.Pending()
   175  	if err != nil {
   176  		t.Fatalf("Could not fetch pending transactions: %v", err)
   177  	}
   178  
   179  	for addr, txs := range pendingTx {
   180  		t.Logf("%0x: %d\n", addr, len(txs))
   181  	}
   182  
   183  	nonce = pool.State().GetNonce(address)
   184  	if nonce != 2 {
   185  		t.Fatalf("Invalid nonce, want 2, got %d", nonce)
   186  	}
   187  }
   188  
   189  func TestInvalidTransactions(t *testing.T) {
   190  	t.Parallel()
   191  
   192  	pool, key := setupTxPool()
   193  	defer pool.Stop()
   194  
   195  	tx := transaction(0, 100, key)
   196  	from, _ := deriveSender(tx)
   197  
   198  	pool.currentState.AddBalance(from, big.NewInt(1))
   199  	if err := pool.AddRemote(tx); err != ErrInsufficientFunds {
   200  		t.Error("expected", ErrInsufficientFunds)
   201  	}
   202  
   203  	balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice()))
   204  	pool.currentState.AddBalance(from, balance)
   205  	if err := pool.AddRemote(tx); err != ErrIntrinsicGas {
   206  		t.Error("expected", ErrIntrinsicGas, "got", err)
   207  	}
   208  
   209  	pool.currentState.SetNonce(from, 1)
   210  	pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
   211  	tx = transaction(0, 100000, key)
   212  	if err := pool.AddRemote(tx); err != ErrNonceTooLow {
   213  		t.Error("expected", ErrNonceTooLow)
   214  	}
   215  
   216  	tx = transaction(1, 100000, key)
   217  	pool.gasPrice = big.NewInt(1000)
   218  	if err := pool.AddRemote(tx); err != ErrUnderpriced {
   219  		t.Error("expected", ErrUnderpriced, "got", err)
   220  	}
   221  	if err := pool.AddLocal(tx); err != nil {
   222  		t.Error("expected", nil, "got", err)
   223  	}
   224  }
   225  
   226  func TestTransactionQueue(t *testing.T) {
   227  	t.Parallel()
   228  
   229  	pool, key := setupTxPool()
   230  	defer pool.Stop()
   231  
   232  	tx := transaction(0, 100, key)
   233  	from, _ := deriveSender(tx)
   234  	pool.currentState.AddBalance(from, big.NewInt(1000))
   235  	pool.lockedReset(nil, nil)
   236  	pool.enqueueTx(tx.Hash(), tx)
   237  
   238  	pool.promoteExecutables([]common.Address{from})
   239  	if len(pool.pending) != 1 {
   240  		t.Error("expected valid txs to be 1 is", len(pool.pending))
   241  	}
   242  
   243  	tx = transaction(1, 100, key)
   244  	from, _ = deriveSender(tx)
   245  	pool.currentState.SetNonce(from, 2)
   246  	pool.enqueueTx(tx.Hash(), tx)
   247  	pool.promoteExecutables([]common.Address{from})
   248  	if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
   249  		t.Error("expected transaction to be in tx pool")
   250  	}
   251  
   252  	if len(pool.queue) > 0 {
   253  		t.Error("expected transaction queue to be empty. is", len(pool.queue))
   254  	}
   255  
   256  	pool, key = setupTxPool()
   257  	defer pool.Stop()
   258  
   259  	tx1 := transaction(0, 100, key)
   260  	tx2 := transaction(10, 100, key)
   261  	tx3 := transaction(11, 100, key)
   262  	from, _ = deriveSender(tx1)
   263  	pool.currentState.AddBalance(from, big.NewInt(1000))
   264  	pool.lockedReset(nil, nil)
   265  
   266  	pool.enqueueTx(tx1.Hash(), tx1)
   267  	pool.enqueueTx(tx2.Hash(), tx2)
   268  	pool.enqueueTx(tx3.Hash(), tx3)
   269  
   270  	pool.promoteExecutables([]common.Address{from})
   271  
   272  	if len(pool.pending) != 1 {
   273  		t.Error("expected tx pool to be 1, got", len(pool.pending))
   274  	}
   275  	if pool.queue[from].Len() != 2 {
   276  		t.Error("expected len(queue) == 2, got", pool.queue[from].Len())
   277  	}
   278  }
   279  
   280  func TestTransactionNegativeValue(t *testing.T) {
   281  	t.Parallel()
   282  
   283  	pool, key := setupTxPool()
   284  	defer pool.Stop()
   285  
   286  	tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key)
   287  	from, _ := deriveSender(tx)
   288  	pool.currentState.AddBalance(from, big.NewInt(1))
   289  	if err := pool.AddRemote(tx); err != ErrNegativeValue {
   290  		t.Error("expected", ErrNegativeValue, "got", err)
   291  	}
   292  }
   293  
   294  func TestTransactionChainFork(t *testing.T) {
   295  	t.Parallel()
   296  
   297  	pool, key := setupTxPool()
   298  	defer pool.Stop()
   299  
   300  	addr := crypto.PubkeyToAddress(key.PublicKey)
   301  	resetState := func() {
   302  		db := rawdb.NewMemoryDatabase()
   303  		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   304  		statedb.AddBalance(addr, big.NewInt(100000000000000))
   305  
   306  		pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
   307  		pool.lockedReset(nil, nil)
   308  	}
   309  	resetState()
   310  
   311  	tx := transaction(0, 100000, key)
   312  	if _, err := pool.add(tx, false); err != nil {
   313  		t.Error("didn't expect error", err)
   314  	}
   315  	pool.removeTx(tx.Hash())
   316  
   317  	resetState()
   318  	if _, err := pool.add(tx, false); err != nil {
   319  		t.Error("didn't expect error", err)
   320  	}
   321  }
   322  
   323  func TestTransactionDoubleNonce(t *testing.T) {
   324  	t.Parallel()
   325  
   326  	pool, key := setupTxPool()
   327  	defer pool.Stop()
   328  
   329  	addr := crypto.PubkeyToAddress(key.PublicKey)
   330  	resetState := func() {
   331  		db := rawdb.NewMemoryDatabase()
   332  		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   333  		statedb.AddBalance(addr, big.NewInt(100000000000000))
   334  
   335  		pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)}
   336  		pool.lockedReset(nil, nil)
   337  	}
   338  	resetState()
   339  
   340  	signer := types.HomesteadSigner{}
   341  	tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key)
   342  	tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key)
   343  	tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key)
   344  
   345  	if replace, err := pool.add(tx1, false); err != nil || replace {
   346  		t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace)
   347  	}
   348  	if replace, err := pool.add(tx2, false); err != nil || !replace {
   349  		t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
   350  	}
   351  	pool.promoteExecutables([]common.Address{addr})
   352  	if pool.pending[addr].Len() != 1 {
   353  		t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
   354  	}
   355  	if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
   356  		t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
   357  	}
   358  	pool.add(tx3, false)
   359  	pool.promoteExecutables([]common.Address{addr})
   360  	if pool.pending[addr].Len() != 1 {
   361  		t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
   362  	}
   363  	if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
   364  		t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
   365  	}
   366  	if len(pool.all) != 1 {
   367  		t.Error("expected 1 total transactions, got", len(pool.all))
   368  	}
   369  }
   370  
   371  func TestTransactionMissingNonce(t *testing.T) {
   372  	t.Parallel()
   373  
   374  	pool, key := setupTxPool()
   375  	defer pool.Stop()
   376  
   377  	addr := crypto.PubkeyToAddress(key.PublicKey)
   378  	pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
   379  	tx := transaction(1, 100000, key)
   380  	if _, err := pool.add(tx, false); err != nil {
   381  		t.Error("didn't expect error", err)
   382  	}
   383  	if len(pool.pending) != 0 {
   384  		t.Error("expected 0 pending transactions, got", len(pool.pending))
   385  	}
   386  	if pool.queue[addr].Len() != 1 {
   387  		t.Error("expected 1 queued transaction, got", pool.queue[addr].Len())
   388  	}
   389  	if len(pool.all) != 1 {
   390  		t.Error("expected 1 total transactions, got", len(pool.all))
   391  	}
   392  }
   393  
   394  func TestTransactionNonceRecovery(t *testing.T) {
   395  	t.Parallel()
   396  
   397  	const n = 10
   398  	pool, key := setupTxPool()
   399  	defer pool.Stop()
   400  
   401  	addr := crypto.PubkeyToAddress(key.PublicKey)
   402  	pool.currentState.SetNonce(addr, n)
   403  	pool.currentState.AddBalance(addr, big.NewInt(100000000000000))
   404  	pool.lockedReset(nil, nil)
   405  
   406  	tx := transaction(n, 100000, key)
   407  	if err := pool.AddRemote(tx); err != nil {
   408  		t.Error(err)
   409  	}
   410  	pool.currentState.SetNonce(addr, n-1)
   411  	pool.lockedReset(nil, nil)
   412  	if fn := pool.pendingState.GetNonce(addr); fn != n-1 {
   413  		t.Errorf("expected nonce to be %d, got %d", n-1, fn)
   414  	}
   415  }
   416  
   417  func TestTransactionDropping(t *testing.T) {
   418  	t.Parallel()
   419  
   420  	pool, key := setupTxPool()
   421  	defer pool.Stop()
   422  
   423  	account, _ := deriveSender(transaction(0, 0, key))
   424  	pool.currentState.AddBalance(account, big.NewInt(1000))
   425  
   426  	var (
   427  		tx0  = transaction(0, 100, key)
   428  		tx1  = transaction(1, 200, key)
   429  		tx2  = transaction(2, 300, key)
   430  		tx10 = transaction(10, 100, key)
   431  		tx11 = transaction(11, 200, key)
   432  		tx12 = transaction(12, 300, key)
   433  	)
   434  	pool.promoteTx(account, tx0.Hash(), tx0)
   435  	pool.promoteTx(account, tx1.Hash(), tx1)
   436  	pool.promoteTx(account, tx2.Hash(), tx2)
   437  	pool.enqueueTx(tx10.Hash(), tx10)
   438  	pool.enqueueTx(tx11.Hash(), tx11)
   439  	pool.enqueueTx(tx12.Hash(), tx12)
   440  
   441  	if pool.pending[account].Len() != 3 {
   442  		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3)
   443  	}
   444  	if pool.queue[account].Len() != 3 {
   445  		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3)
   446  	}
   447  	if len(pool.all) != 6 {
   448  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6)
   449  	}
   450  	pool.lockedReset(nil, nil)
   451  	if pool.pending[account].Len() != 3 {
   452  		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3)
   453  	}
   454  	if pool.queue[account].Len() != 3 {
   455  		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3)
   456  	}
   457  	if len(pool.all) != 6 {
   458  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6)
   459  	}
   460  	pool.currentState.AddBalance(account, big.NewInt(-650))
   461  	pool.lockedReset(nil, nil)
   462  
   463  	if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
   464  		t.Errorf("funded pending transaction missing: %v", tx0)
   465  	}
   466  	if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok {
   467  		t.Errorf("funded pending transaction missing: %v", tx0)
   468  	}
   469  	if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok {
   470  		t.Errorf("out-of-fund pending transaction present: %v", tx1)
   471  	}
   472  	if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
   473  		t.Errorf("funded queued transaction missing: %v", tx10)
   474  	}
   475  	if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok {
   476  		t.Errorf("funded queued transaction missing: %v", tx10)
   477  	}
   478  	if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok {
   479  		t.Errorf("out-of-fund queued transaction present: %v", tx11)
   480  	}
   481  	if len(pool.all) != 4 {
   482  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
   483  	}
   484  	pool.chain.(*testBlockChain).gasLimit = 100
   485  	pool.lockedReset(nil, nil)
   486  
   487  	if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
   488  		t.Errorf("funded pending transaction missing: %v", tx0)
   489  	}
   490  	if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok {
   491  		t.Errorf("over-gased pending transaction present: %v", tx1)
   492  	}
   493  	if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
   494  		t.Errorf("funded queued transaction missing: %v", tx10)
   495  	}
   496  	if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok {
   497  		t.Errorf("over-gased queued transaction present: %v", tx11)
   498  	}
   499  	if len(pool.all) != 2 {
   500  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2)
   501  	}
   502  }
   503  
   504  func TestTransactionPostponing(t *testing.T) {
   505  	t.Parallel()
   506  
   507  	db := rawdb.NewMemoryDatabase()
   508  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   509  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   510  
   511  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
   512  	defer pool.Stop()
   513  
   514  	keys := make([]*ecdsa.PrivateKey, 2)
   515  	accs := make([]common.Address, len(keys))
   516  
   517  	for i := 0; i < len(keys); i++ {
   518  		keys[i], _ = crypto.GenerateKey()
   519  		accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey)
   520  
   521  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100))
   522  	}
   523  	txs := []*types.Transaction{}
   524  	for i, key := range keys {
   525  
   526  		for j := 0; j < 100; j++ {
   527  			var tx *types.Transaction
   528  			if (i+j)%2 == 0 {
   529  				tx = transaction(uint64(j), 25000, key)
   530  			} else {
   531  				tx = transaction(uint64(j), 50000, key)
   532  			}
   533  			txs = append(txs, tx)
   534  		}
   535  	}
   536  	for i, err := range pool.AddRemotes(txs) {
   537  		if err != nil {
   538  			t.Fatalf("tx %d: failed to add transactions: %v", i, err)
   539  		}
   540  	}
   541  	if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) {
   542  		t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs))
   543  	}
   544  	if len(pool.queue) != 0 {
   545  		t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0)
   546  	}
   547  	if len(pool.all) != len(txs) {
   548  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs))
   549  	}
   550  	pool.lockedReset(nil, nil)
   551  	if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) {
   552  		t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs))
   553  	}
   554  	if len(pool.queue) != 0 {
   555  		t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0)
   556  	}
   557  	if len(pool.all) != len(txs) {
   558  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs))
   559  	}
   560  	for _, addr := range accs {
   561  		pool.currentState.AddBalance(addr, big.NewInt(-1))
   562  	}
   563  	pool.lockedReset(nil, nil)
   564  
   565  	if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok {
   566  		t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0])
   567  	}
   568  	if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok {
   569  		t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0])
   570  	}
   571  	for i, tx := range txs[1:100] {
   572  		if i%2 == 1 {
   573  			if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok {
   574  				t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
   575  			}
   576  			if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok {
   577  				t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
   578  			}
   579  		} else {
   580  			if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok {
   581  				t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
   582  			}
   583  			if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok {
   584  				t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
   585  			}
   586  		}
   587  	}
   588  	if pool.pending[accs[1]] != nil {
   589  		t.Errorf("invalidated account still has pending transactions")
   590  	}
   591  	for i, tx := range txs[100:] {
   592  		if i%2 == 1 {
   593  			if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok {
   594  				t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx)
   595  			}
   596  		} else {
   597  			if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok {
   598  				t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx)
   599  			}
   600  		}
   601  	}
   602  	if len(pool.all) != len(txs)/2 {
   603  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)/2)
   604  	}
   605  }
   606  
   607  func TestTransactionGapFilling(t *testing.T) {
   608  	t.Parallel()
   609  
   610  	pool, key := setupTxPool()
   611  	defer pool.Stop()
   612  
   613  	account, _ := deriveSender(transaction(0, 0, key))
   614  	pool.currentState.AddBalance(account, big.NewInt(1000000))
   615  
   616  	events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5)
   617  	sub := pool.txFeed.Subscribe(events)
   618  	defer sub.Unsubscribe()
   619  
   620  	if err := pool.AddRemote(transaction(0, 100000, key)); err != nil {
   621  		t.Fatalf("failed to add pending transaction: %v", err)
   622  	}
   623  	if err := pool.AddRemote(transaction(2, 100000, key)); err != nil {
   624  		t.Fatalf("failed to add queued transaction: %v", err)
   625  	}
   626  	pending, queued := pool.Stats()
   627  	if pending != 1 {
   628  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
   629  	}
   630  	if queued != 1 {
   631  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
   632  	}
   633  	if err := validateEvents(events, 1); err != nil {
   634  		t.Fatalf("original event firing failed: %v", err)
   635  	}
   636  	if err := validateTxPoolInternals(pool); err != nil {
   637  		t.Fatalf("pool internal state corrupted: %v", err)
   638  	}
   639  	if err := pool.AddRemote(transaction(1, 100000, key)); err != nil {
   640  		t.Fatalf("failed to add gapped transaction: %v", err)
   641  	}
   642  	pending, queued = pool.Stats()
   643  	if pending != 3 {
   644  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
   645  	}
   646  	if queued != 0 {
   647  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
   648  	}
   649  	if err := validateEvents(events, 2); err != nil {
   650  		t.Fatalf("gap-filling event firing failed: %v", err)
   651  	}
   652  	if err := validateTxPoolInternals(pool); err != nil {
   653  		t.Fatalf("pool internal state corrupted: %v", err)
   654  	}
   655  }
   656  
   657  func TestTransactionQueueAccountLimiting(t *testing.T) {
   658  	t.Parallel()
   659  
   660  	pool, key := setupTxPool()
   661  	defer pool.Stop()
   662  
   663  	account, _ := deriveSender(transaction(0, 0, key))
   664  	pool.currentState.AddBalance(account, big.NewInt(1000000))
   665  
   666  	for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ {
   667  		if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
   668  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   669  		}
   670  		if len(pool.pending) != 0 {
   671  			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0)
   672  		}
   673  		if i <= testTxPoolConfig.AccountQueue {
   674  			if pool.queue[account].Len() != int(i) {
   675  				t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i)
   676  			}
   677  		} else {
   678  			if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) {
   679  				t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue)
   680  			}
   681  		}
   682  	}
   683  	if len(pool.all) != int(testTxPoolConfig.AccountQueue) {
   684  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue)
   685  	}
   686  }
   687  
   688  func TestTransactionQueueGlobalLimiting(t *testing.T) {
   689  	testTransactionQueueGlobalLimiting(t, false)
   690  }
   691  func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) {
   692  	testTransactionQueueGlobalLimiting(t, true)
   693  }
   694  
   695  func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
   696  	t.Parallel()
   697  
   698  	db := rawdb.NewMemoryDatabase()
   699  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   700  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   701  
   702  	config := testTxPoolConfig
   703  	config.NoLocals = nolocals
   704  	config.GlobalQueue = config.AccountQueue*3 - 1
   705  
   706  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
   707  	defer pool.Stop()
   708  
   709  	keys := make([]*ecdsa.PrivateKey, 5)
   710  	for i := 0; i < len(keys); i++ {
   711  		keys[i], _ = crypto.GenerateKey()
   712  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
   713  	}
   714  	local := keys[len(keys)-1]
   715  
   716  	nonces := make(map[common.Address]uint64)
   717  
   718  	txs := make(types.Transactions, 0, 3*config.GlobalQueue)
   719  	for len(txs) < cap(txs) {
   720  		key := keys[rand.Intn(len(keys)-1)]
   721  		addr := crypto.PubkeyToAddress(key.PublicKey)
   722  
   723  		txs = append(txs, transaction(nonces[addr]+1, 100000, key))
   724  		nonces[addr]++
   725  	}
   726  	pool.AddRemotes(txs)
   727  
   728  	queued := 0
   729  	for addr, list := range pool.queue {
   730  		if list.Len() > int(config.AccountQueue) {
   731  			t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue)
   732  		}
   733  		queued += list.Len()
   734  	}
   735  	if queued > int(config.GlobalQueue) {
   736  		t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue)
   737  	}
   738  	txs = txs[:0]
   739  	for i := uint64(0); i < 3*config.GlobalQueue; i++ {
   740  		txs = append(txs, transaction(i+1, 100000, local))
   741  	}
   742  	pool.AddLocals(txs)
   743  
   744  	if nolocals {
   745  		queued := 0
   746  		for addr, list := range pool.queue {
   747  			if list.Len() > int(config.AccountQueue) {
   748  				t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue)
   749  			}
   750  			queued += list.Len()
   751  		}
   752  		if queued > int(config.GlobalQueue) {
   753  			t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue)
   754  		}
   755  	} else {
   756  		if len(pool.queue) != 1 {
   757  			t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1)
   758  		}
   759  		if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue {
   760  			t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue)
   761  		}
   762  	}
   763  }
   764  
   765  func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) }
   766  func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) {
   767  	testTransactionQueueTimeLimiting(t, true)
   768  }
   769  
   770  func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
   771  	defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
   772  	evictionInterval = time.Second
   773  
   774  	db := rawdb.NewMemoryDatabase()
   775  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   776  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   777  
   778  	config := testTxPoolConfig
   779  	config.Lifetime = time.Second
   780  	config.NoLocals = nolocals
   781  
   782  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
   783  	defer pool.Stop()
   784  
   785  	local, _ := crypto.GenerateKey()
   786  	remote, _ := crypto.GenerateKey()
   787  
   788  	pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
   789  	pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
   790  
   791  	if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
   792  		t.Fatalf("failed to add local transaction: %v", err)
   793  	}
   794  	if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
   795  		t.Fatalf("failed to add remote transaction: %v", err)
   796  	}
   797  	pending, queued := pool.Stats()
   798  	if pending != 0 {
   799  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
   800  	}
   801  	if queued != 2 {
   802  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
   803  	}
   804  	if err := validateTxPoolInternals(pool); err != nil {
   805  		t.Fatalf("pool internal state corrupted: %v", err)
   806  	}
   807  	time.Sleep(2 * config.Lifetime)
   808  
   809  	pending, queued = pool.Stats()
   810  	if pending != 0 {
   811  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
   812  	}
   813  	if nolocals {
   814  		if queued != 0 {
   815  			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
   816  		}
   817  	} else {
   818  		if queued != 1 {
   819  			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
   820  		}
   821  	}
   822  	if err := validateTxPoolInternals(pool); err != nil {
   823  		t.Fatalf("pool internal state corrupted: %v", err)
   824  	}
   825  }
   826  
   827  func TestTransactionPendingLimiting(t *testing.T) {
   828  	t.Parallel()
   829  
   830  	pool, key := setupTxPool()
   831  	defer pool.Stop()
   832  
   833  	account, _ := deriveSender(transaction(0, 0, key))
   834  	pool.currentState.AddBalance(account, big.NewInt(1000000))
   835  
   836  	events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5)
   837  	sub := pool.txFeed.Subscribe(events)
   838  	defer sub.Unsubscribe()
   839  
   840  	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
   841  		if err := pool.AddRemote(transaction(i, 100000, key)); err != nil {
   842  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   843  		}
   844  		if pool.pending[account].Len() != int(i)+1 {
   845  			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1)
   846  		}
   847  		if len(pool.queue) != 0 {
   848  			t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0)
   849  		}
   850  	}
   851  	if len(pool.all) != int(testTxPoolConfig.AccountQueue+5) {
   852  		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5)
   853  	}
   854  	if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil {
   855  		t.Fatalf("event firing failed: %v", err)
   856  	}
   857  	if err := validateTxPoolInternals(pool); err != nil {
   858  		t.Fatalf("pool internal state corrupted: %v", err)
   859  	}
   860  }
   861  
   862  func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) }
   863  func TestTransactionPendingLimitingEquivalency(t *testing.T) {
   864  	testTransactionLimitingEquivalency(t, 0)
   865  }
   866  
   867  func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
   868  	t.Parallel()
   869  
   870  	pool1, key1 := setupTxPool()
   871  	defer pool1.Stop()
   872  
   873  	account1, _ := deriveSender(transaction(0, 0, key1))
   874  	pool1.currentState.AddBalance(account1, big.NewInt(1000000))
   875  
   876  	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
   877  		if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil {
   878  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   879  		}
   880  	}
   881  	pool2, key2 := setupTxPool()
   882  	defer pool2.Stop()
   883  
   884  	account2, _ := deriveSender(transaction(0, 0, key2))
   885  	pool2.currentState.AddBalance(account2, big.NewInt(1000000))
   886  
   887  	txs := []*types.Transaction{}
   888  	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
   889  		txs = append(txs, transaction(origin+i, 100000, key2))
   890  	}
   891  	pool2.AddRemotes(txs)
   892  
   893  	if len(pool1.pending) != len(pool2.pending) {
   894  		t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending))
   895  	}
   896  	if len(pool1.queue) != len(pool2.queue) {
   897  		t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue))
   898  	}
   899  	if len(pool1.all) != len(pool2.all) {
   900  		t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all))
   901  	}
   902  	if err := validateTxPoolInternals(pool1); err != nil {
   903  		t.Errorf("pool 1 internal state corrupted: %v", err)
   904  	}
   905  	if err := validateTxPoolInternals(pool2); err != nil {
   906  		t.Errorf("pool 2 internal state corrupted: %v", err)
   907  	}
   908  }
   909  
   910  func TestTransactionPendingGlobalLimiting(t *testing.T) {
   911  	t.Parallel()
   912  
   913  	db := rawdb.NewMemoryDatabase()
   914  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   915  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   916  
   917  	config := testTxPoolConfig
   918  	config.GlobalSlots = config.AccountSlots * 10
   919  
   920  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
   921  	defer pool.Stop()
   922  
   923  	keys := make([]*ecdsa.PrivateKey, 5)
   924  	for i := 0; i < len(keys); i++ {
   925  		keys[i], _ = crypto.GenerateKey()
   926  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
   927  	}
   928  	nonces := make(map[common.Address]uint64)
   929  
   930  	txs := types.Transactions{}
   931  	for _, key := range keys {
   932  		addr := crypto.PubkeyToAddress(key.PublicKey)
   933  		for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ {
   934  			txs = append(txs, transaction(nonces[addr], 100000, key))
   935  			nonces[addr]++
   936  		}
   937  	}
   938  	pool.AddRemotes(txs)
   939  
   940  	pending := 0
   941  	for _, list := range pool.pending {
   942  		pending += list.Len()
   943  	}
   944  	if pending > int(config.GlobalSlots) {
   945  		t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots)
   946  	}
   947  	if err := validateTxPoolInternals(pool); err != nil {
   948  		t.Fatalf("pool internal state corrupted: %v", err)
   949  	}
   950  }
   951  
   952  func TestTransactionCapClearsFromAll(t *testing.T) {
   953  	t.Parallel()
   954  
   955  	db := rawdb.NewMemoryDatabase()
   956  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   957  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   958  
   959  	config := testTxPoolConfig
   960  	config.AccountSlots = 2
   961  	config.AccountQueue = 2
   962  	config.GlobalSlots = 8
   963  
   964  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
   965  	defer pool.Stop()
   966  
   967  	key, _ := crypto.GenerateKey()
   968  	addr := crypto.PubkeyToAddress(key.PublicKey)
   969  	pool.currentState.AddBalance(addr, big.NewInt(1000000))
   970  
   971  	txs := types.Transactions{}
   972  	for j := 0; j < int(config.GlobalSlots)*2; j++ {
   973  		txs = append(txs, transaction(uint64(j), 100000, key))
   974  	}
   975  	pool.AddRemotes(txs)
   976  	if err := validateTxPoolInternals(pool); err != nil {
   977  		t.Fatalf("pool internal state corrupted: %v", err)
   978  	}
   979  }
   980  
   981  func TestTransactionPendingMinimumAllowance(t *testing.T) {
   982  	t.Parallel()
   983  
   984  	db := rawdb.NewMemoryDatabase()
   985  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   986  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
   987  
   988  	config := testTxPoolConfig
   989  	config.GlobalSlots = 0
   990  
   991  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
   992  	defer pool.Stop()
   993  
   994  	keys := make([]*ecdsa.PrivateKey, 5)
   995  	for i := 0; i < len(keys); i++ {
   996  		keys[i], _ = crypto.GenerateKey()
   997  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
   998  	}
   999  	nonces := make(map[common.Address]uint64)
  1000  
  1001  	txs := types.Transactions{}
  1002  	for _, key := range keys {
  1003  		addr := crypto.PubkeyToAddress(key.PublicKey)
  1004  		for j := 0; j < int(config.AccountSlots)*2; j++ {
  1005  			txs = append(txs, transaction(nonces[addr], 100000, key))
  1006  			nonces[addr]++
  1007  		}
  1008  	}
  1009  	pool.AddRemotes(txs)
  1010  
  1011  	for addr, list := range pool.pending {
  1012  		if list.Len() != int(config.AccountSlots) {
  1013  			t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots)
  1014  		}
  1015  	}
  1016  	if err := validateTxPoolInternals(pool); err != nil {
  1017  		t.Fatalf("pool internal state corrupted: %v", err)
  1018  	}
  1019  }
  1020  
  1021  func TestTransactionPoolRepricing(t *testing.T) {
  1022  	t.Parallel()
  1023  
  1024  	db := rawdb.NewMemoryDatabase()
  1025  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1026  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1027  
  1028  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
  1029  	defer pool.Stop()
  1030  
  1031  	events := make(chan TxPreEvent, 32)
  1032  	sub := pool.txFeed.Subscribe(events)
  1033  	defer sub.Unsubscribe()
  1034  
  1035  	keys := make([]*ecdsa.PrivateKey, 4)
  1036  	for i := 0; i < len(keys); i++ {
  1037  		keys[i], _ = crypto.GenerateKey()
  1038  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
  1039  	}
  1040  	txs := types.Transactions{}
  1041  
  1042  	txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0]))
  1043  	txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0]))
  1044  	txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0]))
  1045  
  1046  	txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1]))
  1047  	txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1]))
  1048  	txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1]))
  1049  
  1050  	txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2]))
  1051  	txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2]))
  1052  	txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2]))
  1053  
  1054  	ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3])
  1055  
  1056  	pool.AddRemotes(txs)
  1057  	pool.AddLocal(ltx)
  1058  
  1059  	pending, queued := pool.Stats()
  1060  	if pending != 7 {
  1061  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7)
  1062  	}
  1063  	if queued != 3 {
  1064  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
  1065  	}
  1066  	if err := validateEvents(events, 7); err != nil {
  1067  		t.Fatalf("original event firing failed: %v", err)
  1068  	}
  1069  	if err := validateTxPoolInternals(pool); err != nil {
  1070  		t.Fatalf("pool internal state corrupted: %v", err)
  1071  	}
  1072  	pool.SetGasPrice(big.NewInt(2))
  1073  
  1074  	pending, queued = pool.Stats()
  1075  	if pending != 2 {
  1076  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
  1077  	}
  1078  	if queued != 5 {
  1079  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5)
  1080  	}
  1081  	if err := validateEvents(events, 0); err != nil {
  1082  		t.Fatalf("reprice event firing failed: %v", err)
  1083  	}
  1084  	if err := validateTxPoolInternals(pool); err != nil {
  1085  		t.Fatalf("pool internal state corrupted: %v", err)
  1086  	}
  1087  	if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced {
  1088  		t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
  1089  	}
  1090  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
  1091  		t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
  1092  	}
  1093  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); err != ErrUnderpriced {
  1094  		t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
  1095  	}
  1096  	if err := validateEvents(events, 0); err != nil {
  1097  		t.Fatalf("post-reprice event firing failed: %v", err)
  1098  	}
  1099  	if err := validateTxPoolInternals(pool); err != nil {
  1100  		t.Fatalf("pool internal state corrupted: %v", err)
  1101  	}
  1102  	tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3])
  1103  	if err := pool.AddLocal(tx); err != nil {
  1104  		t.Fatalf("failed to add underpriced local transaction: %v", err)
  1105  	}
  1106  	if pending, _ = pool.Stats(); pending != 3 {
  1107  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
  1108  	}
  1109  	if err := validateEvents(events, 1); err != nil {
  1110  		t.Fatalf("post-reprice local event firing failed: %v", err)
  1111  	}
  1112  	if err := validateTxPoolInternals(pool); err != nil {
  1113  		t.Fatalf("pool internal state corrupted: %v", err)
  1114  	}
  1115  	if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil {
  1116  		t.Fatalf("failed to add pending transaction: %v", err)
  1117  	}
  1118  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil {
  1119  		t.Fatalf("failed to add pending transaction: %v", err)
  1120  	}
  1121  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil {
  1122  		t.Fatalf("failed to add queued transaction: %v", err)
  1123  	}
  1124  	if err := validateEvents(events, 5); err != nil {
  1125  		t.Fatalf("post-reprice event firing failed: %v", err)
  1126  	}
  1127  	if err := validateTxPoolInternals(pool); err != nil {
  1128  		t.Fatalf("pool internal state corrupted: %v", err)
  1129  	}
  1130  }
  1131  
  1132  func TestTransactionPoolRepricingKeepsLocals(t *testing.T) {
  1133  	t.Parallel()
  1134  
  1135  	db := rawdb.NewMemoryDatabase()
  1136  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1137  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1138  
  1139  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
  1140  	defer pool.Stop()
  1141  
  1142  	keys := make([]*ecdsa.PrivateKey, 3)
  1143  	for i := 0; i < len(keys); i++ {
  1144  		keys[i], _ = crypto.GenerateKey()
  1145  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000))
  1146  	}
  1147  	for i := uint64(0); i < 500; i++ {
  1148  		p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2])
  1149  		if err := pool.AddLocal(p_tx); err != nil {
  1150  			t.Fatal(err)
  1151  		}
  1152  		q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2])
  1153  		if err := pool.AddLocal(q_tx); err != nil {
  1154  			t.Fatal(err)
  1155  		}
  1156  	}
  1157  	pending, queued := pool.Stats()
  1158  	expPending, expQueued := 500, 500
  1159  	validate := func() {
  1160  		pending, queued = pool.Stats()
  1161  		if pending != expPending {
  1162  			t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending)
  1163  		}
  1164  		if queued != expQueued {
  1165  			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued)
  1166  		}
  1167  
  1168  		if err := validateTxPoolInternals(pool); err != nil {
  1169  			t.Fatalf("pool internal state corrupted: %v", err)
  1170  		}
  1171  	}
  1172  	validate()
  1173  
  1174  	pool.SetGasPrice(big.NewInt(2))
  1175  	validate()
  1176  
  1177  	pool.SetGasPrice(big.NewInt(2))
  1178  	pool.SetGasPrice(big.NewInt(4))
  1179  	pool.SetGasPrice(big.NewInt(8))
  1180  	pool.SetGasPrice(big.NewInt(100))
  1181  	validate()
  1182  }
  1183  
  1184  func TestTransactionPoolUnderpricing(t *testing.T) {
  1185  	t.Parallel()
  1186  
  1187  	db := rawdb.NewMemoryDatabase()
  1188  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1189  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1190  
  1191  	config := testTxPoolConfig
  1192  	config.GlobalSlots = 2
  1193  	config.GlobalQueue = 2
  1194  
  1195  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
  1196  	defer pool.Stop()
  1197  
  1198  	events := make(chan TxPreEvent, 32)
  1199  	sub := pool.txFeed.Subscribe(events)
  1200  	defer sub.Unsubscribe()
  1201  
  1202  	keys := make([]*ecdsa.PrivateKey, 3)
  1203  	for i := 0; i < len(keys); i++ {
  1204  		keys[i], _ = crypto.GenerateKey()
  1205  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
  1206  	}
  1207  	txs := types.Transactions{}
  1208  
  1209  	txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0]))
  1210  	txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0]))
  1211  
  1212  	txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1]))
  1213  
  1214  	ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
  1215  
  1216  	pool.AddRemotes(txs)
  1217  	pool.AddLocal(ltx)
  1218  
  1219  	pending, queued := pool.Stats()
  1220  	if pending != 3 {
  1221  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
  1222  	}
  1223  	if queued != 1 {
  1224  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
  1225  	}
  1226  	if err := validateEvents(events, 3); err != nil {
  1227  		t.Fatalf("original event firing failed: %v", err)
  1228  	}
  1229  	if err := validateTxPoolInternals(pool); err != nil {
  1230  		t.Fatalf("pool internal state corrupted: %v", err)
  1231  	}
  1232  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced {
  1233  		t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
  1234  	}
  1235  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil {
  1236  		t.Fatalf("failed to add well priced transaction: %v", err)
  1237  	}
  1238  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil {
  1239  		t.Fatalf("failed to add well priced transaction: %v", err)
  1240  	}
  1241  	if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil {
  1242  		t.Fatalf("failed to add well priced transaction: %v", err)
  1243  	}
  1244  	pending, queued = pool.Stats()
  1245  	if pending != 2 {
  1246  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
  1247  	}
  1248  	if queued != 2 {
  1249  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
  1250  	}
  1251  	if err := validateEvents(events, 2); err != nil {
  1252  		t.Fatalf("additional event firing failed: %v", err)
  1253  	}
  1254  	if err := validateTxPoolInternals(pool); err != nil {
  1255  		t.Fatalf("pool internal state corrupted: %v", err)
  1256  	}
  1257  	tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2])
  1258  	if err := pool.AddLocal(tx); err != nil {
  1259  		t.Fatalf("failed to add underpriced local transaction: %v", err)
  1260  	}
  1261  	pending, queued = pool.Stats()
  1262  	if pending != 2 {
  1263  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
  1264  	}
  1265  	if queued != 2 {
  1266  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
  1267  	}
  1268  	if err := validateEvents(events, 1); err != nil {
  1269  		t.Fatalf("local event firing failed: %v", err)
  1270  	}
  1271  	if err := validateTxPoolInternals(pool); err != nil {
  1272  		t.Fatalf("pool internal state corrupted: %v", err)
  1273  	}
  1274  }
  1275  
  1276  func TestTransactionReplacement(t *testing.T) {
  1277  	t.Parallel()
  1278  
  1279  	db := rawdb.NewMemoryDatabase()
  1280  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1281  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1282  
  1283  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
  1284  	defer pool.Stop()
  1285  
  1286  	events := make(chan TxPreEvent, 32)
  1287  	sub := pool.txFeed.Subscribe(events)
  1288  	defer sub.Unsubscribe()
  1289  
  1290  	key, _ := crypto.GenerateKey()
  1291  	pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000))
  1292  
  1293  	price := int64(100)
  1294  	threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100
  1295  
  1296  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil {
  1297  		t.Fatalf("failed to add original cheap pending transaction: %v", err)
  1298  	}
  1299  	if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
  1300  		t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
  1301  	}
  1302  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil {
  1303  		t.Fatalf("failed to replace original cheap pending transaction: %v", err)
  1304  	}
  1305  	if err := validateEvents(events, 2); err != nil {
  1306  		t.Fatalf("cheap replacement event firing failed: %v", err)
  1307  	}
  1308  
  1309  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil {
  1310  		t.Fatalf("failed to add original proper pending transaction: %v", err)
  1311  	}
  1312  	if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
  1313  		t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
  1314  	}
  1315  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil {
  1316  		t.Fatalf("failed to replace original proper pending transaction: %v", err)
  1317  	}
  1318  	if err := validateEvents(events, 2); err != nil {
  1319  		t.Fatalf("proper replacement event firing failed: %v", err)
  1320  	}
  1321  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil {
  1322  		t.Fatalf("failed to add original cheap queued transaction: %v", err)
  1323  	}
  1324  	if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced {
  1325  		t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
  1326  	}
  1327  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil {
  1328  		t.Fatalf("failed to replace original cheap queued transaction: %v", err)
  1329  	}
  1330  
  1331  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil {
  1332  		t.Fatalf("failed to add original proper queued transaction: %v", err)
  1333  	}
  1334  	if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced {
  1335  		t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
  1336  	}
  1337  	if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil {
  1338  		t.Fatalf("failed to replace original proper queued transaction: %v", err)
  1339  	}
  1340  
  1341  	if err := validateEvents(events, 0); err != nil {
  1342  		t.Fatalf("queued replacement event firing failed: %v", err)
  1343  	}
  1344  	if err := validateTxPoolInternals(pool); err != nil {
  1345  		t.Fatalf("pool internal state corrupted: %v", err)
  1346  	}
  1347  }
  1348  
  1349  func TestTransactionJournaling(t *testing.T)         { testTransactionJournaling(t, false) }
  1350  func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) }
  1351  
  1352  func testTransactionJournaling(t *testing.T, nolocals bool) {
  1353  	t.Parallel()
  1354  
  1355  	file, err := ioutil.TempFile("", "")
  1356  	if err != nil {
  1357  		t.Fatalf("failed to create temporary journal: %v", err)
  1358  	}
  1359  	journal := file.Name()
  1360  	defer os.Remove(journal)
  1361  
  1362  	file.Close()
  1363  	os.Remove(journal)
  1364  
  1365  	db := rawdb.NewMemoryDatabase()
  1366  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1367  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1368  
  1369  	config := testTxPoolConfig
  1370  	config.NoLocals = nolocals
  1371  	config.Journal = journal
  1372  	config.Rejournal = time.Second
  1373  
  1374  	pool := NewTxPool(config, params.TestChainConfig, blockchain, nil)
  1375  
  1376  	local, _ := crypto.GenerateKey()
  1377  	remote, _ := crypto.GenerateKey()
  1378  
  1379  	pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
  1380  	pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
  1381  
  1382  	if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil {
  1383  		t.Fatalf("failed to add local transaction: %v", err)
  1384  	}
  1385  	if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
  1386  		t.Fatalf("failed to add local transaction: %v", err)
  1387  	}
  1388  	if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil {
  1389  		t.Fatalf("failed to add local transaction: %v", err)
  1390  	}
  1391  	if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil {
  1392  		t.Fatalf("failed to add remote transaction: %v", err)
  1393  	}
  1394  	pending, queued := pool.Stats()
  1395  	if pending != 4 {
  1396  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
  1397  	}
  1398  	if queued != 0 {
  1399  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
  1400  	}
  1401  	if err := validateTxPoolInternals(pool); err != nil {
  1402  		t.Fatalf("pool internal state corrupted: %v", err)
  1403  	}
  1404  	pool.Stop()
  1405  	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
  1406  	blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
  1407  
  1408  	pool = NewTxPool(config, params.TestChainConfig, blockchain, nil)
  1409  
  1410  	pending, queued = pool.Stats()
  1411  	if queued != 0 {
  1412  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
  1413  	}
  1414  	if nolocals {
  1415  		if pending != 0 {
  1416  			t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
  1417  		}
  1418  	} else {
  1419  		if pending != 2 {
  1420  			t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
  1421  		}
  1422  	}
  1423  	if err := validateTxPoolInternals(pool); err != nil {
  1424  		t.Fatalf("pool internal state corrupted: %v", err)
  1425  	}
  1426  	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2)
  1427  	pool.lockedReset(nil, nil)
  1428  	time.Sleep(2 * config.Rejournal)
  1429  	pool.Stop()
  1430  
  1431  	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
  1432  	blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)}
  1433  	pool = NewTxPool(config, params.TestChainConfig, blockchain, nil)
  1434  
  1435  	pending, queued = pool.Stats()
  1436  	if pending != 0 {
  1437  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
  1438  	}
  1439  	if nolocals {
  1440  		if queued != 0 {
  1441  			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
  1442  		}
  1443  	} else {
  1444  		if queued != 1 {
  1445  			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
  1446  		}
  1447  	}
  1448  	if err := validateTxPoolInternals(pool); err != nil {
  1449  		t.Fatalf("pool internal state corrupted: %v", err)
  1450  	}
  1451  	pool.Stop()
  1452  }
  1453  
  1454  func TestTransactionStatusCheck(t *testing.T) {
  1455  	t.Parallel()
  1456  
  1457  	db := rawdb.NewMemoryDatabase()
  1458  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
  1459  	blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)}
  1460  
  1461  	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil)
  1462  	defer pool.Stop()
  1463  
  1464  	keys := make([]*ecdsa.PrivateKey, 3)
  1465  	for i := 0; i < len(keys); i++ {
  1466  		keys[i], _ = crypto.GenerateKey()
  1467  		pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
  1468  	}
  1469  	txs := types.Transactions{}
  1470  
  1471  	txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0]))
  1472  	txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1]))
  1473  	txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1]))
  1474  	txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2]))
  1475  
  1476  	pool.AddRemotes(txs)
  1477  
  1478  	pending, queued := pool.Stats()
  1479  	if pending != 2 {
  1480  		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
  1481  	}
  1482  	if queued != 2 {
  1483  		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
  1484  	}
  1485  	if err := validateTxPoolInternals(pool); err != nil {
  1486  		t.Fatalf("pool internal state corrupted: %v", err)
  1487  	}
  1488  	hashes := make([]common.Hash, len(txs))
  1489  	for i, tx := range txs {
  1490  		hashes[i] = tx.Hash()
  1491  	}
  1492  	hashes = append(hashes, common.Hash{})
  1493  
  1494  	statuses := pool.Status(hashes)
  1495  	expect := []TxStatus{TxStatusPending, TxStatusPending, TxStatusQueued, TxStatusQueued, TxStatusUnknown}
  1496  
  1497  	for i := 0; i < len(statuses); i++ {
  1498  		if statuses[i] != expect[i] {
  1499  			t.Errorf("transaction %d: status mismatch: have %v, want %v", i, statuses[i], expect[i])
  1500  		}
  1501  	}
  1502  }
  1503  
  1504  func BenchmarkPendingDemotion100(b *testing.B)   { benchmarkPendingDemotion(b, 100) }
  1505  func BenchmarkPendingDemotion1000(b *testing.B)  { benchmarkPendingDemotion(b, 1000) }
  1506  func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) }
  1507  
  1508  func benchmarkPendingDemotion(b *testing.B, size int) {
  1509  	pool, key := setupTxPool()
  1510  	defer pool.Stop()
  1511  
  1512  	account, _ := deriveSender(transaction(0, 0, key))
  1513  	pool.currentState.AddBalance(account, big.NewInt(1000000))
  1514  
  1515  	for i := 0; i < size; i++ {
  1516  		tx := transaction(uint64(i), 100000, key)
  1517  		pool.promoteTx(account, tx.Hash(), tx)
  1518  	}
  1519  	b.ResetTimer()
  1520  	for i := 0; i < b.N; i++ {
  1521  		pool.demoteUnexecutables()
  1522  	}
  1523  }
  1524  
  1525  func BenchmarkFuturePromotion100(b *testing.B)   { benchmarkFuturePromotion(b, 100) }
  1526  func BenchmarkFuturePromotion1000(b *testing.B)  { benchmarkFuturePromotion(b, 1000) }
  1527  func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) }
  1528  
  1529  func benchmarkFuturePromotion(b *testing.B, size int) {
  1530  	pool, key := setupTxPool()
  1531  	defer pool.Stop()
  1532  
  1533  	account, _ := deriveSender(transaction(0, 0, key))
  1534  	pool.currentState.AddBalance(account, big.NewInt(1000000))
  1535  
  1536  	for i := 0; i < size; i++ {
  1537  		tx := transaction(uint64(1+i), 100000, key)
  1538  		pool.enqueueTx(tx.Hash(), tx)
  1539  	}
  1540  	b.ResetTimer()
  1541  	for i := 0; i < b.N; i++ {
  1542  		pool.promoteExecutables(nil)
  1543  	}
  1544  }
  1545  
  1546  func BenchmarkPoolInsert(b *testing.B) {
  1547  	pool, key := setupTxPool()
  1548  	defer pool.Stop()
  1549  
  1550  	account, _ := deriveSender(transaction(0, 0, key))
  1551  	pool.currentState.AddBalance(account, big.NewInt(1000000))
  1552  
  1553  	txs := make(types.Transactions, b.N)
  1554  	for i := 0; i < b.N; i++ {
  1555  		txs[i] = transaction(uint64(i), 100000, key)
  1556  	}
  1557  	b.ResetTimer()
  1558  	for _, tx := range txs {
  1559  		pool.AddRemote(tx)
  1560  	}
  1561  }
  1562  
  1563  func BenchmarkPoolBatchInsert100(b *testing.B)   { benchmarkPoolBatchInsert(b, 100) }
  1564  func BenchmarkPoolBatchInsert1000(b *testing.B)  { benchmarkPoolBatchInsert(b, 1000) }
  1565  func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) }
  1566  
  1567  func benchmarkPoolBatchInsert(b *testing.B, size int) {
  1568  	pool, key := setupTxPool()
  1569  	defer pool.Stop()
  1570  
  1571  	account, _ := deriveSender(transaction(0, 0, key))
  1572  	pool.currentState.AddBalance(account, big.NewInt(1000000))
  1573  
  1574  	batches := make([]types.Transactions, b.N)
  1575  	for i := 0; i < b.N; i++ {
  1576  		batches[i] = make(types.Transactions, size)
  1577  		for j := 0; j < size; j++ {
  1578  			batches[i][j] = transaction(uint64(size*i+j), 100000, key)
  1579  		}
  1580  	}
  1581  	b.ResetTimer()
  1582  	for _, batch := range batches {
  1583  		pool.AddRemotes(batch)
  1584  	}
  1585  }