aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-07-06 16:51:59 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-07-06 16:51:59 +0800
commit34ec9913f628180d0ace740abfe1362995879c93 (patch)
treeab65a577014ed72b7307b59e42fe9ded25c3420b /core
parent88b4fe7d21bf03bbe01961dc49508bcf4edafb51 (diff)
downloadgo-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar.gz
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar.bz2
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar.lz
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar.xz
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.tar.zst
go-tangerine-34ec9913f628180d0ace740abfe1362995879c93.zip
core: test locals support in txpool queue limits, fix
The commit reworks the transaction pool queue limitation tests to cater for testing local accounts, also testing the nolocal flag. In addition, it also fixes a panic if local transactions exceeded the global queue allowance (no accounts left to drop from) and also fixes queue eviction to operate on all accounts, not just the one being updated.
Diffstat (limited to 'core')
-rw-r--r--core/tx_list.go2
-rw-r--r--core/tx_pool.go14
-rw-r--r--core/tx_pool_test.go264
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))