@@ -209,15 +209,10 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) {
209
209
210
210
pool .lockedReset (nil , nil )
211
211
212
- pendingTx , err := pool .Pending ()
212
+ _ , err := pool .Pending ()
213
213
if err != nil {
214
214
t .Fatalf ("Could not fetch pending transactions: %v" , err )
215
215
}
216
-
217
- for addr , txs := range pendingTx {
218
- t .Logf ("%0x: %d\n " , addr , len (txs ))
219
- }
220
-
221
216
nonce = pool .State ().GetNonce (address )
222
217
if nonce != 2 {
223
218
t .Fatalf ("Invalid nonce, want 2, got %d" , nonce )
@@ -350,7 +345,7 @@ func TestTransactionChainFork(t *testing.T) {
350
345
if _ , err := pool .add (tx , false ); err != nil {
351
346
t .Error ("didn't expect error" , err )
352
347
}
353
- pool .removeTx (tx .Hash ())
348
+ pool .removeTx (tx .Hash (), true )
354
349
355
350
// reset the pool's internal state
356
351
resetState ()
@@ -1388,13 +1383,13 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
1388
1383
t .Fatalf ("adding underpriced pending transaction error mismatch: have %v, want %v" , err , ErrUnderpriced )
1389
1384
}
1390
1385
// Ensure that adding high priced transactions drops cheap ones, but not own
1391
- if err := pool .AddRemote (pricedTransaction (0 , 100000 , big .NewInt (3 ), keys [1 ])); err != nil {
1386
+ if err := pool .AddRemote (pricedTransaction (0 , 100000 , big .NewInt (3 ), keys [1 ])); err != nil { // +K1:0 => -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que -
1392
1387
t .Fatalf ("failed to add well priced transaction: %v" , err )
1393
1388
}
1394
- if err := pool .AddRemote (pricedTransaction (2 , 100000 , big .NewInt (4 ), keys [1 ])); err != nil {
1389
+ if err := pool .AddRemote (pricedTransaction (2 , 100000 , big .NewInt (4 ), keys [1 ])); err != nil { // +K1:2 => -K0:0 => Pend K1:0, K2:0; Que K0:1 K1:2
1395
1390
t .Fatalf ("failed to add well priced transaction: %v" , err )
1396
1391
}
1397
- if err := pool .AddRemote (pricedTransaction (3 , 100000 , big .NewInt (5 ), keys [1 ])); err != nil {
1392
+ if err := pool .AddRemote (pricedTransaction (3 , 100000 , big .NewInt (5 ), keys [1 ])); err != nil { // +K1:3 => -K0:1 => Pend K1:0, K2:0; Que K1:2 K1:3
1398
1393
t .Fatalf ("failed to add well priced transaction: %v" , err )
1399
1394
}
1400
1395
pending , queued = pool .Stats ()
@@ -1404,7 +1399,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
1404
1399
if queued != 2 {
1405
1400
t .Fatalf ("queued transactions mismatched: have %d, want %d" , queued , 2 )
1406
1401
}
1407
- if err := validateEvents (events , 2 ); err != nil {
1402
+ if err := validateEvents (events , 1 ); err != nil {
1408
1403
t .Fatalf ("additional event firing failed: %v" , err )
1409
1404
}
1410
1405
if err := validateTxPoolInternals (pool ); err != nil {
@@ -1430,6 +1425,74 @@ func TestTransactionPoolUnderpricing(t *testing.T) {
1430
1425
}
1431
1426
}
1432
1427
1428
+ // Tests that more expensive transactions push out cheap ones from the pool, but
1429
+ // without producing instability by creating gaps that start jumping transactions
1430
+ // back and forth between queued/pending.
1431
+ func TestTransactionPoolStableUnderpricing (t * testing.T ) {
1432
+ t .Parallel ()
1433
+
1434
+ // Create the pool to test the pricing enforcement with
1435
+ db , _ := ethdb .NewMemDatabase ()
1436
+ statedb , _ := state .New (common.Hash {}, state .NewDatabase (db ))
1437
+ blockchain := & testBlockChain {statedb , 1000000 , new (event.Feed )}
1438
+
1439
+ config := testTxPoolConfig
1440
+ config .GlobalSlots = 128
1441
+ config .GlobalQueue = 0
1442
+
1443
+ pool := NewTxPool (config , params .TestChainConfig , blockchain )
1444
+ defer pool .Stop ()
1445
+
1446
+ // Keep track of transaction events to ensure all executables get announced
1447
+ events := make (chan TxPreEvent , 32 )
1448
+ sub := pool .txFeed .Subscribe (events )
1449
+ defer sub .Unsubscribe ()
1450
+
1451
+ // Create a number of test accounts and fund them
1452
+ keys := make ([]* ecdsa.PrivateKey , 2 )
1453
+ for i := 0 ; i < len (keys ); i ++ {
1454
+ keys [i ], _ = crypto .GenerateKey ()
1455
+ pool .currentState .AddBalance (crypto .PubkeyToAddress (keys [i ].PublicKey ), big .NewInt (1000000 ))
1456
+ }
1457
+ // Fill up the entire queue with the same transaction price points
1458
+ txs := types.Transactions {}
1459
+ for i := uint64 (0 ); i < config .GlobalSlots ; i ++ {
1460
+ txs = append (txs , pricedTransaction (i , 100000 , big .NewInt (1 ), keys [0 ]))
1461
+ }
1462
+ pool .AddRemotes (txs )
1463
+
1464
+ pending , queued := pool .Stats ()
1465
+ if pending != int (config .GlobalSlots ) {
1466
+ t .Fatalf ("pending transactions mismatched: have %d, want %d" , pending , config .GlobalSlots )
1467
+ }
1468
+ if queued != 0 {
1469
+ t .Fatalf ("queued transactions mismatched: have %d, want %d" , queued , 0 )
1470
+ }
1471
+ if err := validateEvents (events , int (config .GlobalSlots )); err != nil {
1472
+ t .Fatalf ("original event firing failed: %v" , err )
1473
+ }
1474
+ if err := validateTxPoolInternals (pool ); err != nil {
1475
+ t .Fatalf ("pool internal state corrupted: %v" , err )
1476
+ }
1477
+ // Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap
1478
+ if err := pool .AddRemote (pricedTransaction (0 , 100000 , big .NewInt (3 ), keys [1 ])); err != nil {
1479
+ t .Fatalf ("failed to add well priced transaction: %v" , err )
1480
+ }
1481
+ pending , queued = pool .Stats ()
1482
+ if pending != int (config .GlobalSlots ) {
1483
+ t .Fatalf ("pending transactions mismatched: have %d, want %d" , pending , config .GlobalSlots )
1484
+ }
1485
+ if queued != 0 {
1486
+ t .Fatalf ("queued transactions mismatched: have %d, want %d" , queued , 0 )
1487
+ }
1488
+ if err := validateEvents (events , 1 ); err != nil {
1489
+ t .Fatalf ("additional event firing failed: %v" , err )
1490
+ }
1491
+ if err := validateTxPoolInternals (pool ); err != nil {
1492
+ t .Fatalf ("pool internal state corrupted: %v" , err )
1493
+ }
1494
+ }
1495
+
1433
1496
// Tests that the pool rejects replacement transactions that don't meet the minimum
1434
1497
// price bump required.
1435
1498
func TestTransactionReplacement (t * testing.T ) {
0 commit comments