diff options
-rw-r--r-- | core/tx_list.go | 2 | ||||
-rw-r--r-- | core/tx_pool.go | 14 | ||||
-rw-r--r-- | core/tx_pool_test.go | 264 |
3 files changed, 197 insertions, 83 deletions
diff --git a/core/tx_list.go b/core/tx_list.go index 4593943be..0d87c20bc 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -477,7 +477,7 @@ func (l *txPricedList) Underpriced(tx *types.Transaction, local *accountSet) boo } // Discard finds a number of most underpriced transactions, removes them from the -// priced list and returs them for further removal from the entire pool. +// priced list and returns them for further removal from the entire pool. func (l *txPricedList) Discard(count int, local *accountSet) types.Transactions { drop := make(types.Transactions, 0, count) // Remote underpriced transactions to drop save := make(types.Transactions, 0, 64) // Local underpriced transactions to keep diff --git a/core/tx_pool.go b/core/tx_pool.go index 46b09c8af..8e2d1b31d 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -716,7 +716,6 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A } } // Iterate over all accounts and promote any executable transactions - queued := uint64(0) for _, addr := range accounts { list := pool.queue[addr] if list == nil { @@ -754,8 +753,6 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A log.Trace("Removed cap-exceeding queued transaction", "hash", hash) } } - queued += uint64(list.Len()) - // Delete the entire queue entry if it became empty. if list.Empty() { delete(pool.queue, addr) @@ -833,19 +830,22 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A pendingRateLimitCounter.Inc(int64(pendingBeforeCap - pending)) } // If we've queued more transactions than the hard limit, drop oldest ones + queued := uint64(0) + for _, list := range pool.queue { + queued += uint64(list.Len()) + } if queued > pool.config.GlobalQueue { // Sort all accounts with queued transactions by heartbeat addresses := make(addresssByHeartbeat, 0, len(pool.queue)) for addr := range pool.queue { - // Don't drop locals - if !pool.locals.contains(addr) { + if !pool.locals.contains(addr) { // don't drop locals addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) } } sort.Sort(addresses) - // Drop transactions until the total is below the limit - for drop := queued - pool.config.GlobalQueue; drop > 0; { + // Drop transactions until the total is below the limit or only locals remain + for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { addr := addresses[len(addresses)-1] list := pool.queue[addr.address] diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 980805ee9..03ece3886 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -47,10 +47,10 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) key, _ := crypto.GenerateKey() - newPool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) - newPool.resetState() + pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + pool.resetState() - return newPool, key + return pool, key } // validateTxPoolInternals checks various consistency invariants within the pool. @@ -125,17 +125,18 @@ func TestStateChangeDuringPoolReset(t *testing.T) { gasLimitFunc := func() *big.Int { return big.NewInt(1000000000) } - txpool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, mux, stateFunc, gasLimitFunc) - txpool.resetState() + pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, mux, stateFunc, gasLimitFunc) + defer pool.Stop() + pool.resetState() - nonce := txpool.State().GetNonce(address) + nonce := pool.State().GetNonce(address) if nonce != 0 { t.Fatalf("Invalid nonce, want 0, got %d", nonce) } - txpool.AddRemotes(types.Transactions{tx0, tx1}) + pool.AddRemotes(types.Transactions{tx0, tx1}) - nonce = txpool.State().GetNonce(address) + nonce = pool.State().GetNonce(address) if nonce != 2 { t.Fatalf("Invalid nonce, want 2, got %d", nonce) } @@ -143,9 +144,9 @@ func TestStateChangeDuringPoolReset(t *testing.T) { // trigger state change in the background trigger = true - txpool.resetState() + pool.resetState() - pendingTx, err := txpool.Pending() + pendingTx, err := pool.Pending() if err != nil { t.Fatalf("Could not fetch pending transactions: %v", err) } @@ -154,7 +155,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) { t.Logf("%0x: %d\n", addr, len(txs)) } - nonce = txpool.State().GetNonce(address) + nonce = pool.State().GetNonce(address) if nonce != 2 { t.Fatalf("Invalid nonce, want 2, got %d", nonce) } @@ -162,6 +163,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) { func TestInvalidTransactions(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() tx := transaction(0, big.NewInt(100), key) from, _ := deriveSender(tx) @@ -196,6 +198,8 @@ func TestInvalidTransactions(t *testing.T) { func TestTransactionQueue(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + tx := transaction(0, big.NewInt(100), key) from, _ := deriveSender(tx) currentState, _ := pool.currentState() @@ -246,6 +250,8 @@ func TestTransactionQueue(t *testing.T) { func TestRemoveTx(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + addr := crypto.PubkeyToAddress(key.PublicKey) currentState, _ := pool.currentState() currentState.AddBalance(addr, big.NewInt(1)) @@ -275,6 +281,7 @@ func TestRemoveTx(t *testing.T) { func TestNegativeValue(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key) from, _ := deriveSender(tx) @@ -287,6 +294,8 @@ func TestNegativeValue(t *testing.T) { func TestTransactionChainFork(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { db, _ := ethdb.NewMemDatabase() @@ -313,6 +322,8 @@ func TestTransactionChainFork(t *testing.T) { func TestTransactionDoubleNonce(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + addr := crypto.PubkeyToAddress(key.PublicKey) resetState := func() { db, _ := ethdb.NewMemDatabase() @@ -361,6 +372,8 @@ func TestTransactionDoubleNonce(t *testing.T) { func TestMissingNonce(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + addr := crypto.PubkeyToAddress(key.PublicKey) currentState, _ := pool.currentState() currentState.AddBalance(addr, big.NewInt(100000000000000)) @@ -382,6 +395,8 @@ func TestMissingNonce(t *testing.T) { func TestNonceRecovery(t *testing.T) { const n = 10 pool, key := setupTxPool() + defer pool.Stop() + addr := crypto.PubkeyToAddress(key.PublicKey) currentState, _ := pool.currentState() currentState.SetNonce(addr, n) @@ -401,6 +416,8 @@ func TestNonceRecovery(t *testing.T) { func TestRemovedTxEvent(t *testing.T) { pool, key := setupTxPool() + defer pool.Stop() + tx := transaction(0, big.NewInt(1000000), key) from, _ := deriveSender(tx) currentState, _ := pool.currentState() @@ -421,6 +438,8 @@ func TestRemovedTxEvent(t *testing.T) { func TestTransactionDropping(t *testing.T) { // Create a test account and fund it pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() @@ -514,6 +533,8 @@ func TestTransactionDropping(t *testing.T) { func TestTransactionPostponing(t *testing.T) { // Create a test account and fund it pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() @@ -588,6 +609,8 @@ func TestTransactionPostponing(t *testing.T) { func TestTransactionQueueAccountLimiting(t *testing.T) { // Create a test account and fund it pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() @@ -619,19 +642,30 @@ func TestTransactionQueueAccountLimiting(t *testing.T) { // Tests that if the transaction count belonging to multiple accounts go above // some threshold, the higher transactions are dropped to prevent DOS attacks. +// +// This logic should not hold for local transactions, unless the local tracking +// mechanism is disabled. func TestTransactionQueueGlobalLimiting(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old uint64) { DefaultTxPoolConfig.GlobalQueue = old }(DefaultTxPoolConfig.GlobalQueue) - DefaultTxPoolConfig.GlobalQueue = DefaultTxPoolConfig.AccountQueue * 3 + testTransactionQueueGlobalLimiting(t, false) +} +func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { + testTransactionQueueGlobalLimiting(t, true) +} +func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { // Create the pool to test the limit enforcement with db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) - pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + config := DefaultTxPoolConfig + config.NoLocals = nolocals + config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() - // Create a number of test accounts and fund them + // Create a number of test accounts and fund them (last one will be the local) state, _ := pool.currentState() keys := make([]*ecdsa.PrivateKey, 5) @@ -639,12 +673,14 @@ func TestTransactionQueueGlobalLimiting(t *testing.T) { keys[i], _ = crypto.GenerateKey() state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) } + local := keys[len(keys)-1] + // Generate and queue a batch of transactions nonces := make(map[common.Address]uint64) - txs := make(types.Transactions, 0, 3*DefaultTxPoolConfig.GlobalQueue) + txs := make(types.Transactions, 0, 3*config.GlobalQueue) for len(txs) < cap(txs) { - key := keys[rand.Intn(len(keys))] + key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account addr := crypto.PubkeyToAddress(key.PublicKey) txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key)) @@ -655,43 +691,114 @@ func TestTransactionQueueGlobalLimiting(t *testing.T) { queued := 0 for addr, list := range pool.queue { - if list.Len() > int(DefaultTxPoolConfig.AccountQueue) { - t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), DefaultTxPoolConfig.AccountQueue) + if list.Len() > int(config.AccountQueue) { + t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) } queued += list.Len() } - if queued > int(DefaultTxPoolConfig.GlobalQueue) { - t.Fatalf("total transactions overflow allowance: %d > %d", queued, DefaultTxPoolConfig.GlobalQueue) + if queued > int(config.GlobalQueue) { + t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) + } + // Generate a batch of transactions from the local account and import them + txs = txs[:0] + for i := uint64(0); i < 3*config.GlobalQueue; i++ { + txs = append(txs, transaction(i+1, big.NewInt(100000), local)) + } + pool.AddLocals(txs) + + // If locals are disabled, the previous eviction algorithm should apply here too + if nolocals { + queued := 0 + for addr, list := range pool.queue { + if list.Len() > int(config.AccountQueue) { + t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) + } + queued += list.Len() + } + if queued > int(config.GlobalQueue) { + t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) + } + } else { + // Local exemptions are enabled, make sure the local account owned the queue + if len(pool.queue) != 1 { + t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) + } + // Also ensure no local transactions are ever dropped, even if above global limits + if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { + t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) + } } } // Tests that if an account remains idle for a prolonged amount of time, any // non-executable transactions queued up are dropped to prevent wasting resources // on shuffling them around. -func TestTransactionQueueTimeLimiting(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old time.Duration) { DefaultTxPoolConfig.Lifetime = old }(DefaultTxPoolConfig.Lifetime) +// +// This logic should not hold for local transactions, unless the local tracking +// mechanism is disabled. +func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) } +func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { testTransactionQueueTimeLimiting(t, true) } + +func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { + // Reduce the eviction interval to a testable amount defer func(old time.Duration) { evictionInterval = old }(evictionInterval) - DefaultTxPoolConfig.Lifetime = time.Second - evictionInterval = time.Second + evictionInterval = 250 * time.Millisecond - // Create a test account and fund it - pool, key := setupTxPool() - account, _ := deriveSender(transaction(0, big.NewInt(0), key)) + // Create the pool to test the non-expiration enforcement + db, _ := ethdb.NewMemDatabase() + statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) + + config := DefaultTxPoolConfig + config.Lifetime = 250 * time.Millisecond + config.NoLocals = nolocals + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() + pool.resetState() + + // Create two test accounts to ensure remotes expire but locals do not + local, _ := crypto.GenerateKey() + remote, _ := crypto.GenerateKey() state, _ := pool.currentState() - state.AddBalance(account, big.NewInt(1000000)) + state.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) + state.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) - // Queue up a batch of transactions - for i := uint64(1); i <= DefaultTxPoolConfig.AccountQueue; i++ { - if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil { - t.Fatalf("tx %d: failed to add transaction: %v", i, err) + // Add the two transactions and ensure they both are queued up + if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil { + t.Fatalf("failed to add local transaction: %v", err) + } + if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil { + t.Fatalf("failed to add remote transaction: %v", err) + } + pending, queued := pool.stats() + if pending != 0 { + t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) + } + if queued != 2 { + t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) + } + if err := validateTxPoolInternals(pool); err != nil { + t.Fatalf("pool internal state corrupted: %v", err) + } + // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains + time.Sleep(2 * config.Lifetime) + + pending, queued = pool.stats() + if pending != 0 { + t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) + } + if nolocals { + if queued != 0 { + t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) + } + } else { + if queued != 1 { + t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) } } - // Wait until at least two expiration cycles hit and make sure the transactions are gone - time.Sleep(2 * evictionInterval) - if len(pool.queue) > 0 { - t.Fatalf("old transactions remained after eviction") + if err := validateTxPoolInternals(pool); err != nil { + t.Fatalf("pool internal state corrupted: %v", err) } } @@ -701,6 +808,8 @@ func TestTransactionQueueTimeLimiting(t *testing.T) { func TestTransactionPendingLimiting(t *testing.T) { // Create a test account and fund it pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() @@ -775,15 +884,15 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { // some hard threshold, the higher transactions are dropped to prevent DOS // attacks. func TestTransactionPendingGlobalLimiting(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old uint64) { DefaultTxPoolConfig.GlobalSlots = old }(DefaultTxPoolConfig.GlobalSlots) - DefaultTxPoolConfig.GlobalSlots = DefaultTxPoolConfig.AccountSlots * 10 - // Create the pool to test the limit enforcement with db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) - pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + config := DefaultTxPoolConfig + config.GlobalSlots = config.AccountSlots * 10 + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() // Create a number of test accounts and fund them @@ -800,7 +909,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { txs := types.Transactions{} for _, key := range keys { addr := crypto.PubkeyToAddress(key.PublicKey) - for j := 0; j < int(DefaultTxPoolConfig.GlobalSlots)/len(keys)*2; j++ { + for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) nonces[addr]++ } @@ -812,8 +921,8 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { for _, list := range pool.pending { pending += list.Len() } - if pending > int(DefaultTxPoolConfig.GlobalSlots) { - t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, DefaultTxPoolConfig.GlobalSlots) + if pending > int(config.GlobalSlots) { + t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) } if err := validateTxPoolInternals(pool); err != nil { t.Fatalf("pool internal state corrupted: %v", err) @@ -822,20 +931,17 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { // Tests that if transactions start being capped, transasctions are also removed from 'all' func TestTransactionCapClearsFromAll(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old uint64) { DefaultTxPoolConfig.AccountSlots = old }(DefaultTxPoolConfig.AccountSlots) - defer func(old uint64) { DefaultTxPoolConfig.AccountQueue = old }(DefaultTxPoolConfig.AccountQueue) - defer func(old uint64) { DefaultTxPoolConfig.GlobalSlots = old }(DefaultTxPoolConfig.GlobalSlots) - - DefaultTxPoolConfig.AccountSlots = 2 - DefaultTxPoolConfig.AccountQueue = 2 - DefaultTxPoolConfig.GlobalSlots = 8 - // Create the pool to test the limit enforcement with db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) - pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + config := DefaultTxPoolConfig + config.AccountSlots = 2 + config.AccountQueue = 2 + config.GlobalSlots = 8 + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() // Create a number of test accounts and fund them @@ -846,7 +952,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) { state.AddBalance(addr, big.NewInt(1000000)) txs := types.Transactions{} - for j := 0; j < int(DefaultTxPoolConfig.GlobalSlots)*2; j++ { + for j := 0; j < int(config.GlobalSlots)*2; j++ { txs = append(txs, transaction(uint64(j), big.NewInt(100000), key)) } // Import the batch and verify that limits have been enforced @@ -860,15 +966,15 @@ func TestTransactionCapClearsFromAll(t *testing.T) { // some hard threshold, if they are under the minimum guaranteed slot count then // the transactions are still kept. func TestTransactionPendingMinimumAllowance(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old uint64) { DefaultTxPoolConfig.GlobalSlots = old }(DefaultTxPoolConfig.GlobalSlots) - DefaultTxPoolConfig.GlobalSlots = 0 - // Create the pool to test the limit enforcement with db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) - pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + config := DefaultTxPoolConfig + config.GlobalSlots = 0 + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() // Create a number of test accounts and fund them @@ -885,7 +991,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) { txs := types.Transactions{} for _, key := range keys { addr := crypto.PubkeyToAddress(key.PublicKey) - for j := 0; j < int(DefaultTxPoolConfig.AccountSlots)*2; j++ { + for j := 0; j < int(config.AccountSlots)*2; j++ { txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) nonces[addr]++ } @@ -894,8 +1000,8 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) { pool.AddRemotes(txs) for addr, list := range pool.pending { - if list.Len() != int(DefaultTxPoolConfig.AccountSlots) { - t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), DefaultTxPoolConfig.AccountSlots) + if list.Len() != int(config.AccountSlots) { + t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) } } if err := validateTxPoolInternals(pool); err != nil { @@ -914,6 +1020,7 @@ func TestTransactionPoolRepricing(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() // Create a number of test accounts and fund them @@ -993,18 +1100,16 @@ func TestTransactionPoolRepricing(t *testing.T) { // // Note, local transactions are never allowed to be dropped. func TestTransactionPoolUnderpricing(t *testing.T) { - // Reduce the queue limits to shorten test time - defer func(old uint64) { DefaultTxPoolConfig.GlobalSlots = old }(DefaultTxPoolConfig.GlobalSlots) - DefaultTxPoolConfig.GlobalSlots = 2 - - defer func(old uint64) { DefaultTxPoolConfig.GlobalQueue = old }(DefaultTxPoolConfig.GlobalQueue) - DefaultTxPoolConfig.GlobalQueue = 2 - // Create the pool to test the pricing enforcement with db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) - pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + config := DefaultTxPoolConfig + config.GlobalSlots = 2 + config.GlobalQueue = 2 + + pool := NewTxPool(config, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() // Create a number of test accounts and fund them @@ -1088,9 +1193,10 @@ func TestTransactionReplacement(t *testing.T) { statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) pool := NewTxPool(DefaultTxPoolConfig, params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) + defer pool.Stop() pool.resetState() - // Create a a test account to add transactions with + // Create a test account to add transactions with key, _ := crypto.GenerateKey() state, _ := pool.currentState() @@ -1153,6 +1259,8 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1 func benchmarkPendingDemotion(b *testing.B, size int) { // Add a batch of transactions to a pool one by one pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() state.AddBalance(account, big.NewInt(1000000)) @@ -1177,6 +1285,8 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1 func benchmarkFuturePromotion(b *testing.B, size int) { // Add a batch of transactions to a pool one by one pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() state.AddBalance(account, big.NewInt(1000000)) @@ -1196,6 +1306,8 @@ func benchmarkFuturePromotion(b *testing.B, size int) { func BenchmarkPoolInsert(b *testing.B) { // Generate a batch of transactions to enqueue into the pool pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() state.AddBalance(account, big.NewInt(1000000)) @@ -1219,6 +1331,8 @@ func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 1 func benchmarkPoolBatchInsert(b *testing.B, size int) { // Generate a batch of transactions to enqueue into the pool pool, key := setupTxPool() + defer pool.Stop() + account, _ := deriveSender(transaction(0, big.NewInt(0), key)) state, _ := pool.currentState() state.AddBalance(account, big.NewInt(1000000)) |