@@ -1438,6 +1438,71 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) {
1438
1438
}
1439
1439
}
1440
1440
1441
+ // Tests that the pool rejects duplicate transactions.
1442
+ func TestTransactionDeduplication (t * testing.T ) {
1443
+ t .Parallel ()
1444
+
1445
+ // Create the pool to test the pricing enforcement with
1446
+ statedb , _ := state .New (common.Hash {}, state .NewDatabase (rawdb .NewMemoryDatabase ()))
1447
+ blockchain := & testBlockChain {statedb , 1000000 , new (event.Feed )}
1448
+
1449
+ pool := NewTxPool (testTxPoolConfig , params .TestChainConfig , blockchain )
1450
+ defer pool .Stop ()
1451
+
1452
+ // Create a test account to add transactions with
1453
+ key , _ := crypto .GenerateKey ()
1454
+ pool .currentState .AddBalance (crypto .PubkeyToAddress (key .PublicKey ), big .NewInt (1000000000 ))
1455
+
1456
+ // Create a batch of transactions and add a few of them
1457
+ txs := make ([]* types.Transaction , 16 )
1458
+ for i := 0 ; i < len (txs ); i ++ {
1459
+ txs [i ] = pricedTransaction (uint64 (i ), 100000 , big .NewInt (1 ), key )
1460
+ }
1461
+ var firsts []* types.Transaction
1462
+ for i := 0 ; i < len (txs ); i += 2 {
1463
+ firsts = append (firsts , txs [i ])
1464
+ }
1465
+ errs := pool .AddRemotesSync (firsts )
1466
+ if len (errs ) != len (firsts ) {
1467
+ t .Fatalf ("first add mismatching result count: have %d, want %d" , len (errs ), len (firsts ))
1468
+ }
1469
+ for i , err := range errs {
1470
+ if err != nil {
1471
+ t .Errorf ("add %d failed: %v" , i , err )
1472
+ }
1473
+ }
1474
+ pending , queued := pool .Stats ()
1475
+ if pending != 1 {
1476
+ t .Fatalf ("pending transactions mismatched: have %d, want %d" , pending , 1 )
1477
+ }
1478
+ if queued != len (txs )/ 2 - 1 {
1479
+ t .Fatalf ("queued transactions mismatched: have %d, want %d" , queued , len (txs )/ 2 - 1 )
1480
+ }
1481
+ // Try to add all of them now and ensure previous ones error out as knowns
1482
+ errs = pool .AddRemotesSync (txs )
1483
+ if len (errs ) != len (txs ) {
1484
+ t .Fatalf ("all add mismatching result count: have %d, want %d" , len (errs ), len (txs ))
1485
+ }
1486
+ for i , err := range errs {
1487
+ if i % 2 == 0 && err == nil {
1488
+ t .Errorf ("add %d succeeded, should have failed as known" , i )
1489
+ }
1490
+ if i % 2 == 1 && err != nil {
1491
+ t .Errorf ("add %d failed: %v" , i , err )
1492
+ }
1493
+ }
1494
+ pending , queued = pool .Stats ()
1495
+ if pending != len (txs ) {
1496
+ t .Fatalf ("pending transactions mismatched: have %d, want %d" , pending , len (txs ))
1497
+ }
1498
+ if queued != 0 {
1499
+ t .Fatalf ("queued transactions mismatched: have %d, want %d" , queued , 0 )
1500
+ }
1501
+ if err := validateTxPoolInternals (pool ); err != nil {
1502
+ t .Fatalf ("pool internal state corrupted: %v" , err )
1503
+ }
1504
+ }
1505
+
1441
1506
// Tests that the pool rejects replacement transactions that don't meet the minimum
1442
1507
// price bump required.
1443
1508
func TestTransactionReplacement (t * testing.T ) {
0 commit comments