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

     1  // Copyright 2015 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  	"crypto/ecdsa"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/ethereumproject/go-ethereum/common"
    25  	"github.com/ethereumproject/go-ethereum/core/state"
    26  	"github.com/ethereumproject/go-ethereum/core/types"
    27  	"github.com/ethereumproject/go-ethereum/crypto"
    28  	"github.com/ethereumproject/go-ethereum/ethdb"
    29  	"github.com/ethereumproject/go-ethereum/event"
    30  )
    31  
    32  func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
    33  	tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(key)
    34  	return tx
    35  }
    36  
    37  func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
    38  	db, _ := ethdb.NewMemDatabase()
    39  	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
    40  
    41  	var m event.TypeMux
    42  	key, _ := crypto.GenerateKey()
    43  	newPool := NewTxPool(testChainConfig(), &m, func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
    44  	newPool.resetState()
    45  	return newPool, key
    46  }
    47  
    48  func deriveSender(tx *types.Transaction) (common.Address, error) {
    49  	return types.Sender(types.BasicSigner{}, tx)
    50  }
    51  
    52  func TestInvalidTransactions(t *testing.T) {
    53  	pool, key := setupTxPool()
    54  
    55  	tx := transaction(0, big.NewInt(100), key)
    56  	if err := pool.Add(tx); err != ErrNonExistentAccount {
    57  		t.Error("expected", ErrNonExistentAccount)
    58  	}
    59  
    60  	from, _ := deriveSender(tx)
    61  	currentState, _ := pool.currentState()
    62  	currentState.AddBalance(from, big.NewInt(1))
    63  	if err := pool.Add(tx); err != ErrInsufficientFunds {
    64  		t.Error("expected", ErrInsufficientFunds)
    65  	}
    66  
    67  	balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice()))
    68  	currentState.AddBalance(from, balance)
    69  	if err := pool.Add(tx); err != ErrIntrinsicGas {
    70  		t.Error("expected", ErrIntrinsicGas, "got", err)
    71  	}
    72  
    73  	currentState.SetNonce(from, 1)
    74  	currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
    75  	tx = transaction(0, big.NewInt(100000), key)
    76  	if err := pool.Add(tx); err != ErrNonce {
    77  		t.Error("expected", ErrNonce)
    78  	}
    79  
    80  	tx = transaction(1, big.NewInt(100000), key)
    81  	pool.minGasPrice = big.NewInt(1000)
    82  	if err := pool.Add(tx); err != ErrCheap {
    83  		t.Error("expected", ErrCheap, "got", err)
    84  	}
    85  
    86  	pool.SetLocal(tx)
    87  	if err := pool.Add(tx); err != nil {
    88  		t.Error("expected", nil, "got", err)
    89  	}
    90  }
    91  
    92  func TestTransactionQueue(t *testing.T) {
    93  	pool, key := setupTxPool()
    94  	tx := transaction(0, big.NewInt(100), key)
    95  	from, _ := tx.From()
    96  	currentState, _ := pool.currentState()
    97  	currentState.AddBalance(from, big.NewInt(1000))
    98  	pool.queueTx(tx.Hash(), tx)
    99  
   100  	pool.checkQueue()
   101  	if len(pool.pending) != 1 {
   102  		t.Error("expected valid txs to be 1 is", len(pool.pending))
   103  	}
   104  
   105  	tx = transaction(1, big.NewInt(100), key)
   106  	from, _ = deriveSender(tx)
   107  	currentState.SetNonce(from, 2)
   108  	pool.queueTx(tx.Hash(), tx)
   109  	pool.checkQueue()
   110  	if _, ok := pool.pending[tx.Hash()]; ok {
   111  		t.Error("expected transaction to be in tx pool")
   112  	}
   113  
   114  	if len(pool.queue[from]) > 0 {
   115  		t.Error("expected transaction queue to be empty. is", len(pool.queue[from]))
   116  	}
   117  
   118  	pool, key = setupTxPool()
   119  	tx1 := transaction(0, big.NewInt(100), key)
   120  	tx2 := transaction(10, big.NewInt(100), key)
   121  	tx3 := transaction(11, big.NewInt(100), key)
   122  	from, _ = tx1.From()
   123  	currentState, _ = pool.currentState()
   124  	currentState.AddBalance(from, big.NewInt(1000))
   125  	pool.queueTx(tx1.Hash(), tx1)
   126  	pool.queueTx(tx2.Hash(), tx2)
   127  	pool.queueTx(tx3.Hash(), tx3)
   128  
   129  	pool.checkQueue()
   130  
   131  	if len(pool.pending) != 1 {
   132  		t.Error("expected tx pool to be 1, got", len(pool.pending))
   133  	}
   134  	if len(pool.queue[from]) != 2 {
   135  		t.Error("expected len(queue) == 2, got", len(pool.queue[from]))
   136  	}
   137  }
   138  
   139  func TestRemoveTx(t *testing.T) {
   140  	pool, key := setupTxPool()
   141  	tx := transaction(0, big.NewInt(100), key)
   142  	from, _ := deriveSender(tx)
   143  	currentState, _ := pool.currentState()
   144  	currentState.AddBalance(from, big.NewInt(1))
   145  	pool.queueTx(tx.Hash(), tx)
   146  	pool.addTx(tx.Hash(), from, tx)
   147  	if len(pool.queue) != 1 {
   148  		t.Error("expected queue to be 1, got", len(pool.queue))
   149  	}
   150  
   151  	if len(pool.pending) != 1 {
   152  		t.Error("expected txs to be 1, got", len(pool.pending))
   153  	}
   154  
   155  	pool.RemoveTx(tx.Hash())
   156  
   157  	if len(pool.queue) > 0 {
   158  		t.Error("expected queue to be 0, got", len(pool.queue))
   159  	}
   160  
   161  	if len(pool.pending) > 0 {
   162  		t.Error("expected txs to be 0, got", len(pool.pending))
   163  	}
   164  }
   165  
   166  func TestNegativeValue(t *testing.T) {
   167  	pool, key := setupTxPool()
   168  
   169  	tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(key)
   170  	from, _ := deriveSender(tx)
   171  	currentState, _ := pool.currentState()
   172  	currentState.AddBalance(from, big.NewInt(1))
   173  	if err := pool.Add(tx); err != ErrNegativeValue {
   174  		t.Error("expected", ErrNegativeValue, "got", err)
   175  	}
   176  }
   177  
   178  func TestTransactionChainFork(t *testing.T) {
   179  	pool, key := setupTxPool()
   180  	addr := crypto.PubkeyToAddress(key.PublicKey)
   181  	resetState := func() {
   182  		db, _ := ethdb.NewMemDatabase()
   183  		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   184  		pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
   185  		currentState, _ := pool.currentState()
   186  		currentState.AddBalance(addr, big.NewInt(100000000000000))
   187  		pool.resetState()
   188  	}
   189  	resetState()
   190  
   191  	tx := transaction(0, big.NewInt(100000), key)
   192  	if err := pool.add(tx); err != nil {
   193  		t.Error("didn't expect error", err)
   194  	}
   195  	pool.RemoveTransactions([]*types.Transaction{tx})
   196  
   197  	// reset the pool's internal state
   198  	resetState()
   199  	if err := pool.add(tx); err != nil {
   200  		t.Error("didn't expect error", err)
   201  	}
   202  }
   203  
   204  func TestTransactionDoubleNonce(t *testing.T) {
   205  	pool, key := setupTxPool()
   206  	addr := crypto.PubkeyToAddress(key.PublicKey)
   207  	resetState := func() {
   208  		db, _ := ethdb.NewMemDatabase()
   209  		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
   210  		pool.currentState = func() (*state.StateDB, error) { return statedb, nil }
   211  		currentState, _ := pool.currentState()
   212  		currentState.AddBalance(addr, big.NewInt(100000000000000))
   213  		pool.resetState()
   214  	}
   215  	resetState()
   216  
   217  	tx := transaction(0, big.NewInt(100000), key)
   218  	tx2 := transaction(0, big.NewInt(1000000), key)
   219  	if err := pool.add(tx); err != nil {
   220  		t.Error("didn't expect error", err)
   221  	}
   222  	if err := pool.add(tx2); err != nil {
   223  		t.Error("didn't expect error", err)
   224  	}
   225  
   226  	pool.checkQueue()
   227  	if len(pool.pending) != 2 {
   228  		t.Error("expected 2 pending txs. Got", len(pool.pending))
   229  	}
   230  }
   231  
   232  func TestMissingNonce(t *testing.T) {
   233  	pool, key := setupTxPool()
   234  	addr := crypto.PubkeyToAddress(key.PublicKey)
   235  	currentState, _ := pool.currentState()
   236  	currentState.AddBalance(addr, big.NewInt(100000000000000))
   237  	tx := transaction(1, big.NewInt(100000), key)
   238  	if err := pool.add(tx); err != nil {
   239  		t.Error("didn't expect error", err)
   240  	}
   241  	if len(pool.pending) != 0 {
   242  		t.Error("expected 0 pending transactions, got", len(pool.pending))
   243  	}
   244  	if len(pool.queue[addr]) != 1 {
   245  		t.Error("expected 1 queued transaction, got", len(pool.queue[addr]))
   246  	}
   247  }
   248  
   249  func TestNonceRecovery(t *testing.T) {
   250  	const n = 10
   251  	pool, key := setupTxPool()
   252  	addr := crypto.PubkeyToAddress(key.PublicKey)
   253  	currentState, _ := pool.currentState()
   254  	currentState.SetNonce(addr, n)
   255  	currentState.AddBalance(addr, big.NewInt(100000000000000))
   256  	pool.resetState()
   257  	tx := transaction(n, big.NewInt(100000), key)
   258  	if err := pool.Add(tx); err != nil {
   259  		t.Error(err)
   260  	}
   261  	// simulate some weird re-order of transactions and missing nonce(s)
   262  	currentState.SetNonce(addr, n-1)
   263  	pool.resetState()
   264  	if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
   265  		t.Errorf("expected nonce to be %d, got %d", n+1, fn)
   266  	}
   267  }
   268  
   269  func TestRemovedTxEvent(t *testing.T) {
   270  	pool, key := setupTxPool()
   271  	tx := transaction(0, big.NewInt(1000000), key)
   272  	from, _ := deriveSender(tx)
   273  	currentState, _ := pool.currentState()
   274  	currentState.AddBalance(from, big.NewInt(1000000000000))
   275  	pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
   276  	pool.eventMux.Post(ChainHeadEvent{nil})
   277  	if len(pool.pending) != 1 {
   278  		t.Error("expected 1 pending tx, got", len(pool.pending))
   279  	}
   280  }
   281  
   282  // Tests that if an account runs out of funds, any pending and queued transactions
   283  // are dropped.
   284  func TestTransactionDropping(t *testing.T) {
   285  	// Create a test account and fund it
   286  	pool, key := setupTxPool()
   287  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   288  
   289  	state, _ := pool.currentState()
   290  	state.AddBalance(account, big.NewInt(1000))
   291  
   292  	// Add some pending and some queued transactions
   293  	var (
   294  		tx0  = transaction(0, big.NewInt(100), key)
   295  		tx1  = transaction(1, big.NewInt(200), key)
   296  		tx10 = transaction(10, big.NewInt(100), key)
   297  		tx11 = transaction(11, big.NewInt(200), key)
   298  	)
   299  	pool.addTx(tx0.Hash(), account, tx0)
   300  	pool.addTx(tx1.Hash(), account, tx1)
   301  	pool.queueTx(tx10.Hash(), tx10)
   302  	pool.queueTx(tx11.Hash(), tx11)
   303  
   304  	// Check that pre and post validations leave the pool as is
   305  	if len(pool.pending) != 2 {
   306  		t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), 2)
   307  	}
   308  	if len(pool.queue[account]) != 2 {
   309  		t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 2)
   310  	}
   311  	pool.resetState()
   312  	if len(pool.pending) != 2 {
   313  		t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), 2)
   314  	}
   315  	if len(pool.queue[account]) != 2 {
   316  		t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 2)
   317  	}
   318  	// Reduce the balance of the account, and check that invalidated transactions are dropped
   319  	state.AddBalance(account, big.NewInt(-750))
   320  	pool.resetState()
   321  
   322  	if _, ok := pool.pending[tx0.Hash()]; !ok {
   323  		t.Errorf("funded pending transaction missing: %v", tx0)
   324  	}
   325  	if _, ok := pool.pending[tx1.Hash()]; ok {
   326  		t.Errorf("out-of-fund pending transaction present: %v", tx1)
   327  	}
   328  	if _, ok := pool.queue[account][tx10.Hash()]; !ok {
   329  		t.Errorf("funded queued transaction missing: %v", tx10)
   330  	}
   331  	if _, ok := pool.queue[account][tx11.Hash()]; ok {
   332  		t.Errorf("out-of-fund queued transaction present: %v", tx11)
   333  	}
   334  }
   335  
   336  // Tests that if a transaction is dropped from the current pending pool (e.g. out
   337  // of fund), all consecutive (still valid, but not executable) transactions are
   338  // postponed back into the future queue to prevent broadcasting them.
   339  func TestTransactionPostponing(t *testing.T) {
   340  	// Create a test account and fund it
   341  	pool, key := setupTxPool()
   342  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   343  
   344  	state, _ := pool.currentState()
   345  	state.AddBalance(account, big.NewInt(1000))
   346  
   347  	// Add a batch consecutive pending transactions for validation
   348  	txns := []*types.Transaction{}
   349  	for i := 0; i < 100; i++ {
   350  		var tx *types.Transaction
   351  		if i%2 == 0 {
   352  			tx = transaction(uint64(i), big.NewInt(100), key)
   353  		} else {
   354  			tx = transaction(uint64(i), big.NewInt(500), key)
   355  		}
   356  		pool.addTx(tx.Hash(), account, tx)
   357  		txns = append(txns, tx)
   358  	}
   359  	// Check that pre and post validations leave the pool as is
   360  	if len(pool.pending) != len(txns) {
   361  		t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), len(txns))
   362  	}
   363  	if len(pool.queue[account]) != 0 {
   364  		t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 0)
   365  	}
   366  	pool.resetState()
   367  	if len(pool.pending) != len(txns) {
   368  		t.Errorf("pending transaction mismatch: have %d, want %d", len(pool.pending), len(txns))
   369  	}
   370  	if len(pool.queue[account]) != 0 {
   371  		t.Errorf("queued transaction mismatch: have %d, want %d", len(pool.queue), 0)
   372  	}
   373  	// Reduce the balance of the account, and check that transactions are reorganised
   374  	state.AddBalance(account, big.NewInt(-750))
   375  	pool.resetState()
   376  
   377  	if _, ok := pool.pending[txns[0].Hash()]; !ok {
   378  		t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
   379  	}
   380  	if _, ok := pool.queue[account][txns[0].Hash()]; ok {
   381  		t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0])
   382  	}
   383  	for i, tx := range txns[1:] {
   384  		if i%2 == 1 {
   385  			if _, ok := pool.pending[tx.Hash()]; ok {
   386  				t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
   387  			}
   388  			if _, ok := pool.queue[account][tx.Hash()]; !ok {
   389  				t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
   390  			}
   391  		} else {
   392  			if _, ok := pool.pending[tx.Hash()]; ok {
   393  				t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
   394  			}
   395  			if _, ok := pool.queue[account][tx.Hash()]; ok {
   396  				t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
   397  			}
   398  		}
   399  	}
   400  }
   401  
   402  // Tests that if the transaction count belonging to a single account goes above
   403  // some threshold, the higher transactions are dropped to prevent DOS attacks.
   404  func TestTransactionQueueLimiting(t *testing.T) {
   405  	// Create a test account and fund it
   406  	pool, key := setupTxPool()
   407  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   408  
   409  	state, _ := pool.currentState()
   410  	state.AddBalance(account, big.NewInt(1000000))
   411  
   412  	// Keep queuing up transactions and make sure all above a limit are dropped
   413  	for i := uint64(1); i <= maxQueued+5; i++ {
   414  		if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
   415  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   416  		}
   417  		if len(pool.pending) != 0 {
   418  			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0)
   419  		}
   420  		if i <= maxQueued {
   421  			if len(pool.queue[account]) != int(i) {
   422  				t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, len(pool.queue[account]), i)
   423  			}
   424  		} else {
   425  			if len(pool.queue[account]) != maxQueued {
   426  				t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, len(pool.queue[account]), maxQueued)
   427  			}
   428  		}
   429  	}
   430  }
   431  
   432  // Tests that even if the transaction count belonging to a single account goes
   433  // above some threshold, as long as the transactions are executable, they are
   434  // accepted.
   435  func TestTransactionPendingLimiting(t *testing.T) {
   436  	// Create a test account and fund it
   437  	pool, key := setupTxPool()
   438  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   439  
   440  	state, _ := pool.currentState()
   441  	state.AddBalance(account, big.NewInt(1000000))
   442  
   443  	// Keep queuing up transactions and make sure all above a limit are dropped
   444  	for i := uint64(0); i < maxQueued+5; i++ {
   445  		if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil {
   446  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   447  		}
   448  		if len(pool.pending) != int(i)+1 {
   449  			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), i+1)
   450  		}
   451  		if len(pool.queue[account]) != 0 {
   452  			t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, len(pool.queue[account]), 0)
   453  		}
   454  	}
   455  }
   456  
   457  // Tests that the transaction limits are enforced the same way irrelevant whether
   458  // the transactions are added one by one or in batches.
   459  func TestTransactionQueueLimitingEquivalency(t *testing.T)   { testTransactionLimitingEquivalency(t, 1) }
   460  func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) }
   461  
   462  func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
   463  	// Add a batch of transactions to a pool one by one
   464  	pool1, key1 := setupTxPool()
   465  	account1, _ := deriveSender(transaction(0, big.NewInt(0), key1))
   466  	state1, _ := pool1.currentState()
   467  	state1.AddBalance(account1, big.NewInt(1000000))
   468  
   469  	for i := uint64(0); i < maxQueued+5; i++ {
   470  		if err := pool1.Add(transaction(origin+i, big.NewInt(100000), key1)); err != nil {
   471  			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
   472  		}
   473  	}
   474  	// Add a batch of transactions to a pool in one bit batch
   475  	pool2, key2 := setupTxPool()
   476  	account2, _ := transaction(0, big.NewInt(0), key2).From()
   477  	state2, _ := pool2.currentState()
   478  	state2.AddBalance(account2, big.NewInt(1000000))
   479  
   480  	txns := []*types.Transaction{}
   481  	for i := uint64(0); i < maxQueued+5; i++ {
   482  		txns = append(txns, transaction(origin+i, big.NewInt(100000), key2))
   483  	}
   484  	pool2.AddTransactions(txns)
   485  
   486  	// Ensure the batch optimization honors the same pool mechanics
   487  	if len(pool1.pending) != len(pool2.pending) {
   488  		t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending))
   489  	}
   490  	if len(pool1.queue[account1]) != len(pool2.queue[account2]) {
   491  		t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue[account1]), len(pool2.queue[account2]))
   492  	}
   493  }
   494  
   495  // Benchmarks the speed of validating the contents of the pending queue of the
   496  // transaction pool.
   497  func BenchmarkValidatePool100(b *testing.B)   { benchmarkValidatePool(b, 100) }
   498  func BenchmarkValidatePool1000(b *testing.B)  { benchmarkValidatePool(b, 1000) }
   499  func BenchmarkValidatePool10000(b *testing.B) { benchmarkValidatePool(b, 10000) }
   500  
   501  func benchmarkValidatePool(b *testing.B, size int) {
   502  	// Add a batch of transactions to a pool one by one
   503  	pool, key := setupTxPool()
   504  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   505  	state, _ := pool.currentState()
   506  	state.AddBalance(account, big.NewInt(1000000))
   507  
   508  	for i := 0; i < size; i++ {
   509  		tx := transaction(uint64(i), big.NewInt(100000), key)
   510  		pool.addTx(tx.Hash(), account, tx)
   511  	}
   512  	// Benchmark the speed of pool validation
   513  	b.ResetTimer()
   514  	for i := 0; i < b.N; i++ {
   515  		pool.validatePool()
   516  	}
   517  }
   518  
   519  // Benchmarks the speed of scheduling the contents of the future queue of the
   520  // transaction pool.
   521  func BenchmarkCheckQueue100(b *testing.B)   { benchmarkCheckQueue(b, 100) }
   522  func BenchmarkCheckQueue1000(b *testing.B)  { benchmarkCheckQueue(b, 1000) }
   523  func BenchmarkCheckQueue10000(b *testing.B) { benchmarkCheckQueue(b, 10000) }
   524  
   525  func benchmarkCheckQueue(b *testing.B, size int) {
   526  	// Add a batch of transactions to a pool one by one
   527  	pool, key := setupTxPool()
   528  	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
   529  	state, _ := pool.currentState()
   530  	state.AddBalance(account, big.NewInt(1000000))
   531  
   532  	for i := 0; i < size; i++ {
   533  		tx := transaction(uint64(1+i), big.NewInt(100000), key)
   534  		pool.queueTx(tx.Hash(), tx)
   535  	}
   536  	// Benchmark the speed of pool validation
   537  	b.ResetTimer()
   538  	for i := 0; i < b.N; i++ {
   539  		pool.checkQueue()
   540  	}
   541  }