Tests that when the pool reaches its global transaction limit, underpriced transactions are gradually shifted out for more expensive ones and any gapped pending transactions are moved into the queue. Note, local transactions are never allowed to be dropped.
(t *testing.T)
| 1322 | // |
| 1323 | // Note, local transactions are never allowed to be dropped. |
| 1324 | func TestTransactionPoolUnderpricing(t *testing.T) { |
| 1325 | t.Parallel() |
| 1326 | |
| 1327 | // Create the pool to test the pricing enforcement with |
| 1328 | statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemDatabase())) |
| 1329 | blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} |
| 1330 | |
| 1331 | config := testTxPoolConfig |
| 1332 | config.GlobalSlots = 2 |
| 1333 | config.GlobalQueue = 2 |
| 1334 | |
| 1335 | pool := NewTxPool(config, configs.TestChainConfig, blockchain) |
| 1336 | defer pool.Stop() |
| 1337 | |
| 1338 | // Keep track of transaction events to ensure all executables get announced |
| 1339 | events := make(chan NewTxsEvent, 32) |
| 1340 | sub := pool.txFeed.Subscribe(events) |
| 1341 | defer sub.Unsubscribe() |
| 1342 | |
| 1343 | // Create a number of test accounts and fund them |
| 1344 | keys := make([]*ecdsa.PrivateKey, 4) |
| 1345 | for i := 0; i < len(keys); i++ { |
| 1346 | keys[i], _ = crypto.GenerateKey() |
| 1347 | pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) |
| 1348 | } |
| 1349 | // Generate and queue a batch of transactions, both pending and queued |
| 1350 | txs := types.Transactions{} |
| 1351 | |
| 1352 | txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) |
| 1353 | txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) |
| 1354 | |
| 1355 | txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) |
| 1356 | |
| 1357 | ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) |
| 1358 | |
| 1359 | // Import the batch and that both pending and queued transactions match up |
| 1360 | pool.AddRemotes(txs) |
| 1361 | pool.AddLocal(ltx) |
| 1362 | |
| 1363 | pending, queued := pool.Stats() |
| 1364 | if pending != 3 { |
| 1365 | t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) |
| 1366 | } |
| 1367 | if queued != 1 { |
| 1368 | t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) |
| 1369 | } |
| 1370 | if err := validateEvents(events, 3); err != nil { |
| 1371 | t.Fatalf("original event firing failed: %v", err) |
| 1372 | } |
| 1373 | if err := validateTxPoolInternals(pool); err != nil { |
| 1374 | t.Fatalf("pool internal state corrupted: %v", err) |
| 1375 | } |
| 1376 | // Ensure that adding an underpriced transaction on block limit fails |
| 1377 | if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { |
| 1378 | t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) |
| 1379 | } |
| 1380 | // Ensure that adding high priced transactions drops cheap ones, but not own |
| 1381 | 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 - |
nothing calls this directly
no test coverage detected