github.com/anthdm/go-ethereum@v1.8.4-0.20180412101906-60516c83b011/core/tx_pool_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "io/ioutil" 23 "math/big" 24 "math/rand" 25 "os" 26 "testing" 27 "time" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/core/state" 31 "github.com/ethereum/go-ethereum/core/types" 32 "github.com/ethereum/go-ethereum/crypto" 33 "github.com/ethereum/go-ethereum/ethdb" 34 "github.com/ethereum/go-ethereum/event" 35 "github.com/ethereum/go-ethereum/params" 36 ) 37 38 // testTxPoolConfig is a transaction pool configuration without stateful disk 39 // sideeffects used during testing. 40 var testTxPoolConfig TxPoolConfig 41 42 func init() { 43 testTxPoolConfig = DefaultTxPoolConfig 44 testTxPoolConfig.Journal = "" 45 } 46 47 type testBlockChain struct { 48 statedb *state.StateDB 49 gasLimit uint64 50 chainHeadFeed *event.Feed 51 } 52 53 func (bc *testBlockChain) CurrentBlock() *types.Block { 54 return types.NewBlock(&types.Header{ 55 GasLimit: bc.gasLimit, 56 }, nil, nil, nil) 57 } 58 59 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 60 return bc.CurrentBlock() 61 } 62 63 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 64 return bc.statedb, nil 65 } 66 67 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 68 return bc.chainHeadFeed.Subscribe(ch) 69 } 70 71 func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction { 72 return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) 73 } 74 75 func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 76 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) 77 return tx 78 } 79 80 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 81 diskdb, _ := ethdb.NewMemDatabase() 82 statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb)) 83 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 84 85 key, _ := crypto.GenerateKey() 86 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 87 88 return pool, key 89 } 90 91 // validateTxPoolInternals checks various consistency invariants within the pool. 92 func validateTxPoolInternals(pool *TxPool) error { 93 pool.mu.RLock() 94 defer pool.mu.RUnlock() 95 96 // Ensure the total transaction set is consistent with pending + queued 97 pending, queued := pool.stats() 98 if total := len(pool.all); total != pending+queued { 99 return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) 100 } 101 if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { 102 return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued) 103 } 104 // Ensure the next nonce to assign is the correct one 105 for addr, txs := range pool.pending { 106 // Find the last transaction 107 var last uint64 108 for nonce := range txs.txs.items { 109 if last < nonce { 110 last = nonce 111 } 112 } 113 if nonce := pool.pendingState.GetNonce(addr); nonce != last+1 { 114 return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) 115 } 116 } 117 return nil 118 } 119 120 // validateEvents checks that the correct number of transaction addition events 121 // were fired on the pool's event feed. 122 func validateEvents(events chan TxPreEvent, count int) error { 123 for i := 0; i < count; i++ { 124 select { 125 case <-events: 126 case <-time.After(time.Second): 127 return fmt.Errorf("event #%d not fired", i) 128 } 129 } 130 select { 131 case tx := <-events: 132 return fmt.Errorf("more than %d events fired: %v", count, tx.Tx) 133 134 case <-time.After(50 * time.Millisecond): 135 // This branch should be "default", but it's a data race between goroutines, 136 // reading the event channel and pushng into it, so better wait a bit ensuring 137 // really nothing gets injected. 138 } 139 return nil 140 } 141 142 func deriveSender(tx *types.Transaction) (common.Address, error) { 143 return types.Sender(types.HomesteadSigner{}, tx) 144 } 145 146 type testChain struct { 147 *testBlockChain 148 address common.Address 149 trigger *bool 150 } 151 152 // testChain.State() is used multiple times to reset the pending state. 153 // when simulate is true it will create a state that indicates 154 // that tx0 and tx1 are included in the chain. 155 func (c *testChain) State() (*state.StateDB, error) { 156 // delay "state change" by one. The tx pool fetches the 157 // state multiple times and by delaying it a bit we simulate 158 // a state change between those fetches. 159 stdb := c.statedb 160 if *c.trigger { 161 db, _ := ethdb.NewMemDatabase() 162 c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 163 // simulate that the new head block included tx0 and tx1 164 c.statedb.SetNonce(c.address, 2) 165 c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether)) 166 *c.trigger = false 167 } 168 return stdb, nil 169 } 170 171 // This test simulates a scenario where a new block is imported during a 172 // state reset and tests whether the pending state is in sync with the 173 // block head event that initiated the resetState(). 174 func TestStateChangeDuringTransactionPoolReset(t *testing.T) { 175 t.Parallel() 176 177 var ( 178 db, _ = ethdb.NewMemDatabase() 179 key, _ = crypto.GenerateKey() 180 address = crypto.PubkeyToAddress(key.PublicKey) 181 statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 182 trigger = false 183 ) 184 185 // setup pool with 2 transaction in it 186 statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) 187 blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger} 188 189 tx0 := transaction(0, 100000, key) 190 tx1 := transaction(1, 100000, key) 191 192 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 193 defer pool.Stop() 194 195 nonce := pool.State().GetNonce(address) 196 if nonce != 0 { 197 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 198 } 199 200 pool.AddRemotes(types.Transactions{tx0, tx1}) 201 202 nonce = pool.State().GetNonce(address) 203 if nonce != 2 { 204 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 205 } 206 207 // trigger state change in the background 208 trigger = true 209 210 pool.lockedReset(nil, nil) 211 212 _, err := pool.Pending() 213 if err != nil { 214 t.Fatalf("Could not fetch pending transactions: %v", err) 215 } 216 nonce = pool.State().GetNonce(address) 217 if nonce != 2 { 218 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 219 } 220 } 221 222 func TestInvalidTransactions(t *testing.T) { 223 t.Parallel() 224 225 pool, key := setupTxPool() 226 defer pool.Stop() 227 228 tx := transaction(0, 100, key) 229 from, _ := deriveSender(tx) 230 231 pool.currentState.AddBalance(from, big.NewInt(1)) 232 if err := pool.AddRemote(tx); err != ErrInsufficientFunds { 233 t.Error("expected", ErrInsufficientFunds) 234 } 235 236 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) 237 pool.currentState.AddBalance(from, balance) 238 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 239 t.Error("expected", ErrIntrinsicGas, "got", err) 240 } 241 242 pool.currentState.SetNonce(from, 1) 243 pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) 244 tx = transaction(0, 100000, key) 245 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 246 t.Error("expected", ErrNonceTooLow) 247 } 248 249 tx = transaction(1, 100000, key) 250 pool.gasPrice = big.NewInt(1000) 251 if err := pool.AddRemote(tx); err != ErrUnderpriced { 252 t.Error("expected", ErrUnderpriced, "got", err) 253 } 254 if err := pool.AddLocal(tx); err != nil { 255 t.Error("expected", nil, "got", err) 256 } 257 } 258 259 func TestTransactionQueue(t *testing.T) { 260 t.Parallel() 261 262 pool, key := setupTxPool() 263 defer pool.Stop() 264 265 tx := transaction(0, 100, key) 266 from, _ := deriveSender(tx) 267 pool.currentState.AddBalance(from, big.NewInt(1000)) 268 pool.lockedReset(nil, nil) 269 pool.enqueueTx(tx.Hash(), tx) 270 271 pool.promoteExecutables([]common.Address{from}) 272 if len(pool.pending) != 1 { 273 t.Error("expected valid txs to be 1 is", len(pool.pending)) 274 } 275 276 tx = transaction(1, 100, key) 277 from, _ = deriveSender(tx) 278 pool.currentState.SetNonce(from, 2) 279 pool.enqueueTx(tx.Hash(), tx) 280 pool.promoteExecutables([]common.Address{from}) 281 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 282 t.Error("expected transaction to be in tx pool") 283 } 284 285 if len(pool.queue) > 0 { 286 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 287 } 288 289 pool, key = setupTxPool() 290 defer pool.Stop() 291 292 tx1 := transaction(0, 100, key) 293 tx2 := transaction(10, 100, key) 294 tx3 := transaction(11, 100, key) 295 from, _ = deriveSender(tx1) 296 pool.currentState.AddBalance(from, big.NewInt(1000)) 297 pool.lockedReset(nil, nil) 298 299 pool.enqueueTx(tx1.Hash(), tx1) 300 pool.enqueueTx(tx2.Hash(), tx2) 301 pool.enqueueTx(tx3.Hash(), tx3) 302 303 pool.promoteExecutables([]common.Address{from}) 304 305 if len(pool.pending) != 1 { 306 t.Error("expected tx pool to be 1, got", len(pool.pending)) 307 } 308 if pool.queue[from].Len() != 2 { 309 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 310 } 311 } 312 313 func TestTransactionNegativeValue(t *testing.T) { 314 t.Parallel() 315 316 pool, key := setupTxPool() 317 defer pool.Stop() 318 319 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) 320 from, _ := deriveSender(tx) 321 pool.currentState.AddBalance(from, big.NewInt(1)) 322 if err := pool.AddRemote(tx); err != ErrNegativeValue { 323 t.Error("expected", ErrNegativeValue, "got", err) 324 } 325 } 326 327 func TestTransactionChainFork(t *testing.T) { 328 t.Parallel() 329 330 pool, key := setupTxPool() 331 defer pool.Stop() 332 333 addr := crypto.PubkeyToAddress(key.PublicKey) 334 resetState := func() { 335 db, _ := ethdb.NewMemDatabase() 336 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 337 statedb.AddBalance(addr, big.NewInt(100000000000000)) 338 339 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 340 pool.lockedReset(nil, nil) 341 } 342 resetState() 343 344 tx := transaction(0, 100000, key) 345 if _, err := pool.add(tx, false); err != nil { 346 t.Error("didn't expect error", err) 347 } 348 pool.removeTx(tx.Hash(), true) 349 350 // reset the pool's internal state 351 resetState() 352 if _, err := pool.add(tx, false); err != nil { 353 t.Error("didn't expect error", err) 354 } 355 } 356 357 func TestTransactionDoubleNonce(t *testing.T) { 358 t.Parallel() 359 360 pool, key := setupTxPool() 361 defer pool.Stop() 362 363 addr := crypto.PubkeyToAddress(key.PublicKey) 364 resetState := func() { 365 db, _ := ethdb.NewMemDatabase() 366 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 367 statedb.AddBalance(addr, big.NewInt(100000000000000)) 368 369 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 370 pool.lockedReset(nil, nil) 371 } 372 resetState() 373 374 signer := types.HomesteadSigner{} 375 tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key) 376 tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key) 377 tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) 378 379 // Add the first two transaction, ensure higher priced stays only 380 if replace, err := pool.add(tx1, false); err != nil || replace { 381 t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) 382 } 383 if replace, err := pool.add(tx2, false); err != nil || !replace { 384 t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) 385 } 386 pool.promoteExecutables([]common.Address{addr}) 387 if pool.pending[addr].Len() != 1 { 388 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 389 } 390 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 391 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 392 } 393 // Add the third transaction and ensure it's not saved (smaller price) 394 pool.add(tx3, false) 395 pool.promoteExecutables([]common.Address{addr}) 396 if pool.pending[addr].Len() != 1 { 397 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 398 } 399 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 400 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 401 } 402 // Ensure the total transaction count is correct 403 if len(pool.all) != 1 { 404 t.Error("expected 1 total transactions, got", len(pool.all)) 405 } 406 } 407 408 func TestTransactionMissingNonce(t *testing.T) { 409 t.Parallel() 410 411 pool, key := setupTxPool() 412 defer pool.Stop() 413 414 addr := crypto.PubkeyToAddress(key.PublicKey) 415 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 416 tx := transaction(1, 100000, key) 417 if _, err := pool.add(tx, false); err != nil { 418 t.Error("didn't expect error", err) 419 } 420 if len(pool.pending) != 0 { 421 t.Error("expected 0 pending transactions, got", len(pool.pending)) 422 } 423 if pool.queue[addr].Len() != 1 { 424 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 425 } 426 if len(pool.all) != 1 { 427 t.Error("expected 1 total transactions, got", len(pool.all)) 428 } 429 } 430 431 func TestTransactionNonceRecovery(t *testing.T) { 432 t.Parallel() 433 434 const n = 10 435 pool, key := setupTxPool() 436 defer pool.Stop() 437 438 addr := crypto.PubkeyToAddress(key.PublicKey) 439 pool.currentState.SetNonce(addr, n) 440 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 441 pool.lockedReset(nil, nil) 442 443 tx := transaction(n, 100000, key) 444 if err := pool.AddRemote(tx); err != nil { 445 t.Error(err) 446 } 447 // simulate some weird re-order of transactions and missing nonce(s) 448 pool.currentState.SetNonce(addr, n-1) 449 pool.lockedReset(nil, nil) 450 if fn := pool.pendingState.GetNonce(addr); fn != n-1 { 451 t.Errorf("expected nonce to be %d, got %d", n-1, fn) 452 } 453 } 454 455 // Tests that if an account runs out of funds, any pending and queued transactions 456 // are dropped. 457 func TestTransactionDropping(t *testing.T) { 458 t.Parallel() 459 460 // Create a test account and fund it 461 pool, key := setupTxPool() 462 defer pool.Stop() 463 464 account, _ := deriveSender(transaction(0, 0, key)) 465 pool.currentState.AddBalance(account, big.NewInt(1000)) 466 467 // Add some pending and some queued transactions 468 var ( 469 tx0 = transaction(0, 100, key) 470 tx1 = transaction(1, 200, key) 471 tx2 = transaction(2, 300, key) 472 tx10 = transaction(10, 100, key) 473 tx11 = transaction(11, 200, key) 474 tx12 = transaction(12, 300, key) 475 ) 476 pool.promoteTx(account, tx0.Hash(), tx0) 477 pool.promoteTx(account, tx1.Hash(), tx1) 478 pool.promoteTx(account, tx2.Hash(), tx2) 479 pool.enqueueTx(tx10.Hash(), tx10) 480 pool.enqueueTx(tx11.Hash(), tx11) 481 pool.enqueueTx(tx12.Hash(), tx12) 482 483 // Check that pre and post validations leave the pool as is 484 if pool.pending[account].Len() != 3 { 485 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 486 } 487 if pool.queue[account].Len() != 3 { 488 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 489 } 490 if len(pool.all) != 6 { 491 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 492 } 493 pool.lockedReset(nil, nil) 494 if pool.pending[account].Len() != 3 { 495 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 496 } 497 if pool.queue[account].Len() != 3 { 498 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 499 } 500 if len(pool.all) != 6 { 501 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 502 } 503 // Reduce the balance of the account, and check that invalidated transactions are dropped 504 pool.currentState.AddBalance(account, big.NewInt(-650)) 505 pool.lockedReset(nil, nil) 506 507 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 508 t.Errorf("funded pending transaction missing: %v", tx0) 509 } 510 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { 511 t.Errorf("funded pending transaction missing: %v", tx0) 512 } 513 if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { 514 t.Errorf("out-of-fund pending transaction present: %v", tx1) 515 } 516 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 517 t.Errorf("funded queued transaction missing: %v", tx10) 518 } 519 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { 520 t.Errorf("funded queued transaction missing: %v", tx10) 521 } 522 if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { 523 t.Errorf("out-of-fund queued transaction present: %v", tx11) 524 } 525 if len(pool.all) != 4 { 526 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) 527 } 528 // Reduce the block gas limit, check that invalidated transactions are dropped 529 pool.chain.(*testBlockChain).gasLimit = 100 530 pool.lockedReset(nil, nil) 531 532 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 533 t.Errorf("funded pending transaction missing: %v", tx0) 534 } 535 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { 536 t.Errorf("over-gased pending transaction present: %v", tx1) 537 } 538 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 539 t.Errorf("funded queued transaction missing: %v", tx10) 540 } 541 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { 542 t.Errorf("over-gased queued transaction present: %v", tx11) 543 } 544 if len(pool.all) != 2 { 545 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2) 546 } 547 } 548 549 // Tests that if a transaction is dropped from the current pending pool (e.g. out 550 // of fund), all consecutive (still valid, but not executable) transactions are 551 // postponed back into the future queue to prevent broadcasting them. 552 func TestTransactionPostponing(t *testing.T) { 553 t.Parallel() 554 555 // Create the pool to test the postponing with 556 db, _ := ethdb.NewMemDatabase() 557 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 558 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 559 560 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 561 defer pool.Stop() 562 563 // Create two test accounts to produce different gap profiles with 564 keys := make([]*ecdsa.PrivateKey, 2) 565 accs := make([]common.Address, len(keys)) 566 567 for i := 0; i < len(keys); i++ { 568 keys[i], _ = crypto.GenerateKey() 569 accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 570 571 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100)) 572 } 573 // Add a batch consecutive pending transactions for validation 574 txs := []*types.Transaction{} 575 for i, key := range keys { 576 577 for j := 0; j < 100; j++ { 578 var tx *types.Transaction 579 if (i+j)%2 == 0 { 580 tx = transaction(uint64(j), 25000, key) 581 } else { 582 tx = transaction(uint64(j), 50000, key) 583 } 584 txs = append(txs, tx) 585 } 586 } 587 for i, err := range pool.AddRemotes(txs) { 588 if err != nil { 589 t.Fatalf("tx %d: failed to add transactions: %v", i, err) 590 } 591 } 592 // Check that pre and post validations leave the pool as is 593 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 594 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 595 } 596 if len(pool.queue) != 0 { 597 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 598 } 599 if len(pool.all) != len(txs) { 600 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) 601 } 602 pool.lockedReset(nil, nil) 603 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 604 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 605 } 606 if len(pool.queue) != 0 { 607 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 608 } 609 if len(pool.all) != len(txs) { 610 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) 611 } 612 // Reduce the balance of the account, and check that transactions are reorganised 613 for _, addr := range accs { 614 pool.currentState.AddBalance(addr, big.NewInt(-1)) 615 } 616 pool.lockedReset(nil, nil) 617 618 // The first account's first transaction remains valid, check that subsequent 619 // ones are either filtered out, or queued up for later. 620 if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok { 621 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0]) 622 } 623 if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok { 624 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0]) 625 } 626 for i, tx := range txs[1:100] { 627 if i%2 == 1 { 628 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 629 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 630 } 631 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok { 632 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 633 } 634 } else { 635 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 636 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 637 } 638 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok { 639 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 640 } 641 } 642 } 643 // The second account's first transaction got invalid, check that all transactions 644 // are either filtered out, or queued up for later. 645 if pool.pending[accs[1]] != nil { 646 t.Errorf("invalidated account still has pending transactions") 647 } 648 for i, tx := range txs[100:] { 649 if i%2 == 1 { 650 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok { 651 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx) 652 } 653 } else { 654 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok { 655 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx) 656 } 657 } 658 } 659 if len(pool.all) != len(txs)/2 { 660 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)/2) 661 } 662 } 663 664 // Tests that if the transaction pool has both executable and non-executable 665 // transactions from an origin account, filling the nonce gap moves all queued 666 // ones into the pending pool. 667 func TestTransactionGapFilling(t *testing.T) { 668 t.Parallel() 669 670 // Create a test account and fund it 671 pool, key := setupTxPool() 672 defer pool.Stop() 673 674 account, _ := deriveSender(transaction(0, 0, key)) 675 pool.currentState.AddBalance(account, big.NewInt(1000000)) 676 677 // Keep track of transaction events to ensure all executables get announced 678 events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5) 679 sub := pool.txFeed.Subscribe(events) 680 defer sub.Unsubscribe() 681 682 // Create a pending and a queued transaction with a nonce-gap in between 683 if err := pool.AddRemote(transaction(0, 100000, key)); err != nil { 684 t.Fatalf("failed to add pending transaction: %v", err) 685 } 686 if err := pool.AddRemote(transaction(2, 100000, key)); err != nil { 687 t.Fatalf("failed to add queued transaction: %v", err) 688 } 689 pending, queued := pool.Stats() 690 if pending != 1 { 691 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) 692 } 693 if queued != 1 { 694 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 695 } 696 if err := validateEvents(events, 1); err != nil { 697 t.Fatalf("original event firing failed: %v", err) 698 } 699 if err := validateTxPoolInternals(pool); err != nil { 700 t.Fatalf("pool internal state corrupted: %v", err) 701 } 702 // Fill the nonce gap and ensure all transactions become pending 703 if err := pool.AddRemote(transaction(1, 100000, key)); err != nil { 704 t.Fatalf("failed to add gapped transaction: %v", err) 705 } 706 pending, queued = pool.Stats() 707 if pending != 3 { 708 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 709 } 710 if queued != 0 { 711 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 712 } 713 if err := validateEvents(events, 2); err != nil { 714 t.Fatalf("gap-filling event firing failed: %v", err) 715 } 716 if err := validateTxPoolInternals(pool); err != nil { 717 t.Fatalf("pool internal state corrupted: %v", err) 718 } 719 } 720 721 // Tests that if the transaction count belonging to a single account goes above 722 // some threshold, the higher transactions are dropped to prevent DOS attacks. 723 func TestTransactionQueueAccountLimiting(t *testing.T) { 724 t.Parallel() 725 726 // Create a test account and fund it 727 pool, key := setupTxPool() 728 defer pool.Stop() 729 730 account, _ := deriveSender(transaction(0, 0, key)) 731 pool.currentState.AddBalance(account, big.NewInt(1000000)) 732 733 // Keep queuing up transactions and make sure all above a limit are dropped 734 for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { 735 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 736 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 737 } 738 if len(pool.pending) != 0 { 739 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 740 } 741 if i <= testTxPoolConfig.AccountQueue { 742 if pool.queue[account].Len() != int(i) { 743 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 744 } 745 } else { 746 if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) { 747 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue) 748 } 749 } 750 } 751 if len(pool.all) != int(testTxPoolConfig.AccountQueue) { 752 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue) 753 } 754 } 755 756 // Tests that if the transaction count belonging to multiple accounts go above 757 // some threshold, the higher transactions are dropped to prevent DOS attacks. 758 // 759 // This logic should not hold for local transactions, unless the local tracking 760 // mechanism is disabled. 761 func TestTransactionQueueGlobalLimiting(t *testing.T) { 762 testTransactionQueueGlobalLimiting(t, false) 763 } 764 func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { 765 testTransactionQueueGlobalLimiting(t, true) 766 } 767 768 func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { 769 t.Parallel() 770 771 // Create the pool to test the limit enforcement with 772 db, _ := ethdb.NewMemDatabase() 773 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 774 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 775 776 config := testTxPoolConfig 777 config.NoLocals = nolocals 778 config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) 779 780 pool := NewTxPool(config, params.TestChainConfig, blockchain) 781 defer pool.Stop() 782 783 // Create a number of test accounts and fund them (last one will be the local) 784 keys := make([]*ecdsa.PrivateKey, 5) 785 for i := 0; i < len(keys); i++ { 786 keys[i], _ = crypto.GenerateKey() 787 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 788 } 789 local := keys[len(keys)-1] 790 791 // Generate and queue a batch of transactions 792 nonces := make(map[common.Address]uint64) 793 794 txs := make(types.Transactions, 0, 3*config.GlobalQueue) 795 for len(txs) < cap(txs) { 796 key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account 797 addr := crypto.PubkeyToAddress(key.PublicKey) 798 799 txs = append(txs, transaction(nonces[addr]+1, 100000, key)) 800 nonces[addr]++ 801 } 802 // Import the batch and verify that limits have been enforced 803 pool.AddRemotes(txs) 804 805 queued := 0 806 for addr, list := range pool.queue { 807 if list.Len() > int(config.AccountQueue) { 808 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 809 } 810 queued += list.Len() 811 } 812 if queued > int(config.GlobalQueue) { 813 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 814 } 815 // Generate a batch of transactions from the local account and import them 816 txs = txs[:0] 817 for i := uint64(0); i < 3*config.GlobalQueue; i++ { 818 txs = append(txs, transaction(i+1, 100000, local)) 819 } 820 pool.AddLocals(txs) 821 822 // If locals are disabled, the previous eviction algorithm should apply here too 823 if nolocals { 824 queued := 0 825 for addr, list := range pool.queue { 826 if list.Len() > int(config.AccountQueue) { 827 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 828 } 829 queued += list.Len() 830 } 831 if queued > int(config.GlobalQueue) { 832 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 833 } 834 } else { 835 // Local exemptions are enabled, make sure the local account owned the queue 836 if len(pool.queue) != 1 { 837 t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) 838 } 839 // Also ensure no local transactions are ever dropped, even if above global limits 840 if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { 841 t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) 842 } 843 } 844 } 845 846 // Tests that if an account remains idle for a prolonged amount of time, any 847 // non-executable transactions queued up are dropped to prevent wasting resources 848 // on shuffling them around. 849 // 850 // This logic should not hold for local transactions, unless the local tracking 851 // mechanism is disabled. 852 func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) } 853 func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { testTransactionQueueTimeLimiting(t, true) } 854 855 func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { 856 // Reduce the eviction interval to a testable amount 857 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 858 evictionInterval = time.Second 859 860 // Create the pool to test the non-expiration enforcement 861 db, _ := ethdb.NewMemDatabase() 862 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 863 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 864 865 config := testTxPoolConfig 866 config.Lifetime = time.Second 867 config.NoLocals = nolocals 868 869 pool := NewTxPool(config, params.TestChainConfig, blockchain) 870 defer pool.Stop() 871 872 // Create two test accounts to ensure remotes expire but locals do not 873 local, _ := crypto.GenerateKey() 874 remote, _ := crypto.GenerateKey() 875 876 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 877 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 878 879 // Add the two transactions and ensure they both are queued up 880 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 881 t.Fatalf("failed to add local transaction: %v", err) 882 } 883 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { 884 t.Fatalf("failed to add remote transaction: %v", err) 885 } 886 pending, queued := pool.Stats() 887 if pending != 0 { 888 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 889 } 890 if queued != 2 { 891 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 892 } 893 if err := validateTxPoolInternals(pool); err != nil { 894 t.Fatalf("pool internal state corrupted: %v", err) 895 } 896 // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains 897 time.Sleep(2 * config.Lifetime) 898 899 pending, queued = pool.Stats() 900 if pending != 0 { 901 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 902 } 903 if nolocals { 904 if queued != 0 { 905 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 906 } 907 } else { 908 if queued != 1 { 909 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 910 } 911 } 912 if err := validateTxPoolInternals(pool); err != nil { 913 t.Fatalf("pool internal state corrupted: %v", err) 914 } 915 } 916 917 // Tests that even if the transaction count belonging to a single account goes 918 // above some threshold, as long as the transactions are executable, they are 919 // accepted. 920 func TestTransactionPendingLimiting(t *testing.T) { 921 t.Parallel() 922 923 // Create a test account and fund it 924 pool, key := setupTxPool() 925 defer pool.Stop() 926 927 account, _ := deriveSender(transaction(0, 0, key)) 928 pool.currentState.AddBalance(account, big.NewInt(1000000)) 929 930 // Keep track of transaction events to ensure all executables get announced 931 events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5) 932 sub := pool.txFeed.Subscribe(events) 933 defer sub.Unsubscribe() 934 935 // Keep queuing up transactions and make sure all above a limit are dropped 936 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 937 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 938 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 939 } 940 if pool.pending[account].Len() != int(i)+1 { 941 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 942 } 943 if len(pool.queue) != 0 { 944 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 945 } 946 } 947 if len(pool.all) != int(testTxPoolConfig.AccountQueue+5) { 948 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5) 949 } 950 if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { 951 t.Fatalf("event firing failed: %v", err) 952 } 953 if err := validateTxPoolInternals(pool); err != nil { 954 t.Fatalf("pool internal state corrupted: %v", err) 955 } 956 } 957 958 // Tests that the transaction limits are enforced the same way irrelevant whether 959 // the transactions are added one by one or in batches. 960 func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) } 961 func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) } 962 963 func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { 964 t.Parallel() 965 966 // Add a batch of transactions to a pool one by one 967 pool1, key1 := setupTxPool() 968 defer pool1.Stop() 969 970 account1, _ := deriveSender(transaction(0, 0, key1)) 971 pool1.currentState.AddBalance(account1, big.NewInt(1000000)) 972 973 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 974 if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil { 975 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 976 } 977 } 978 // Add a batch of transactions to a pool in one big batch 979 pool2, key2 := setupTxPool() 980 defer pool2.Stop() 981 982 account2, _ := deriveSender(transaction(0, 0, key2)) 983 pool2.currentState.AddBalance(account2, big.NewInt(1000000)) 984 985 txs := []*types.Transaction{} 986 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 987 txs = append(txs, transaction(origin+i, 100000, key2)) 988 } 989 pool2.AddRemotes(txs) 990 991 // Ensure the batch optimization honors the same pool mechanics 992 if len(pool1.pending) != len(pool2.pending) { 993 t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending)) 994 } 995 if len(pool1.queue) != len(pool2.queue) { 996 t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue)) 997 } 998 if len(pool1.all) != len(pool2.all) { 999 t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all)) 1000 } 1001 if err := validateTxPoolInternals(pool1); err != nil { 1002 t.Errorf("pool 1 internal state corrupted: %v", err) 1003 } 1004 if err := validateTxPoolInternals(pool2); err != nil { 1005 t.Errorf("pool 2 internal state corrupted: %v", err) 1006 } 1007 } 1008 1009 // Tests that if the transaction count belonging to multiple accounts go above 1010 // some hard threshold, the higher transactions are dropped to prevent DOS 1011 // attacks. 1012 func TestTransactionPendingGlobalLimiting(t *testing.T) { 1013 t.Parallel() 1014 1015 // Create the pool to test the limit enforcement with 1016 db, _ := ethdb.NewMemDatabase() 1017 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1018 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1019 1020 config := testTxPoolConfig 1021 config.GlobalSlots = config.AccountSlots * 10 1022 1023 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1024 defer pool.Stop() 1025 1026 // Create a number of test accounts and fund them 1027 keys := make([]*ecdsa.PrivateKey, 5) 1028 for i := 0; i < len(keys); i++ { 1029 keys[i], _ = crypto.GenerateKey() 1030 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1031 } 1032 // Generate and queue a batch of transactions 1033 nonces := make(map[common.Address]uint64) 1034 1035 txs := types.Transactions{} 1036 for _, key := range keys { 1037 addr := crypto.PubkeyToAddress(key.PublicKey) 1038 for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { 1039 txs = append(txs, transaction(nonces[addr], 100000, key)) 1040 nonces[addr]++ 1041 } 1042 } 1043 // Import the batch and verify that limits have been enforced 1044 pool.AddRemotes(txs) 1045 1046 pending := 0 1047 for _, list := range pool.pending { 1048 pending += list.Len() 1049 } 1050 if pending > int(config.GlobalSlots) { 1051 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) 1052 } 1053 if err := validateTxPoolInternals(pool); err != nil { 1054 t.Fatalf("pool internal state corrupted: %v", err) 1055 } 1056 } 1057 1058 // Tests that if transactions start being capped, transactions are also removed from 'all' 1059 func TestTransactionCapClearsFromAll(t *testing.T) { 1060 t.Parallel() 1061 1062 // Create the pool to test the limit enforcement with 1063 db, _ := ethdb.NewMemDatabase() 1064 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1065 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1066 1067 config := testTxPoolConfig 1068 config.AccountSlots = 2 1069 config.AccountQueue = 2 1070 config.GlobalSlots = 8 1071 1072 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1073 defer pool.Stop() 1074 1075 // Create a number of test accounts and fund them 1076 key, _ := crypto.GenerateKey() 1077 addr := crypto.PubkeyToAddress(key.PublicKey) 1078 pool.currentState.AddBalance(addr, big.NewInt(1000000)) 1079 1080 txs := types.Transactions{} 1081 for j := 0; j < int(config.GlobalSlots)*2; j++ { 1082 txs = append(txs, transaction(uint64(j), 100000, key)) 1083 } 1084 // Import the batch and verify that limits have been enforced 1085 pool.AddRemotes(txs) 1086 if err := validateTxPoolInternals(pool); err != nil { 1087 t.Fatalf("pool internal state corrupted: %v", err) 1088 } 1089 } 1090 1091 // Tests that if the transaction count belonging to multiple accounts go above 1092 // some hard threshold, if they are under the minimum guaranteed slot count then 1093 // the transactions are still kept. 1094 func TestTransactionPendingMinimumAllowance(t *testing.T) { 1095 t.Parallel() 1096 1097 // Create the pool to test the limit enforcement with 1098 db, _ := ethdb.NewMemDatabase() 1099 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1100 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1101 1102 config := testTxPoolConfig 1103 config.GlobalSlots = 0 1104 1105 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1106 defer pool.Stop() 1107 1108 // Create a number of test accounts and fund them 1109 keys := make([]*ecdsa.PrivateKey, 5) 1110 for i := 0; i < len(keys); i++ { 1111 keys[i], _ = crypto.GenerateKey() 1112 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1113 } 1114 // Generate and queue a batch of transactions 1115 nonces := make(map[common.Address]uint64) 1116 1117 txs := types.Transactions{} 1118 for _, key := range keys { 1119 addr := crypto.PubkeyToAddress(key.PublicKey) 1120 for j := 0; j < int(config.AccountSlots)*2; j++ { 1121 txs = append(txs, transaction(nonces[addr], 100000, key)) 1122 nonces[addr]++ 1123 } 1124 } 1125 // Import the batch and verify that limits have been enforced 1126 pool.AddRemotes(txs) 1127 1128 for addr, list := range pool.pending { 1129 if list.Len() != int(config.AccountSlots) { 1130 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) 1131 } 1132 } 1133 if err := validateTxPoolInternals(pool); err != nil { 1134 t.Fatalf("pool internal state corrupted: %v", err) 1135 } 1136 } 1137 1138 // Tests that setting the transaction pool gas price to a higher value correctly 1139 // discards everything cheaper than that and moves any gapped transactions back 1140 // from the pending pool to the queue. 1141 // 1142 // Note, local transactions are never allowed to be dropped. 1143 func TestTransactionPoolRepricing(t *testing.T) { 1144 t.Parallel() 1145 1146 // Create the pool to test the pricing enforcement with 1147 db, _ := ethdb.NewMemDatabase() 1148 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1149 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1150 1151 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1152 defer pool.Stop() 1153 1154 // Keep track of transaction events to ensure all executables get announced 1155 events := make(chan TxPreEvent, 32) 1156 sub := pool.txFeed.Subscribe(events) 1157 defer sub.Unsubscribe() 1158 1159 // Create a number of test accounts and fund them 1160 keys := make([]*ecdsa.PrivateKey, 4) 1161 for i := 0; i < len(keys); i++ { 1162 keys[i], _ = crypto.GenerateKey() 1163 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1164 } 1165 // Generate and queue a batch of transactions, both pending and queued 1166 txs := types.Transactions{} 1167 1168 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) 1169 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) 1170 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) 1171 1172 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) 1173 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1])) 1174 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1])) 1175 1176 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2])) 1177 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) 1178 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2])) 1179 1180 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3]) 1181 1182 // Import the batch and that both pending and queued transactions match up 1183 pool.AddRemotes(txs) 1184 pool.AddLocal(ltx) 1185 1186 pending, queued := pool.Stats() 1187 if pending != 7 { 1188 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) 1189 } 1190 if queued != 3 { 1191 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1192 } 1193 if err := validateEvents(events, 7); err != nil { 1194 t.Fatalf("original event firing failed: %v", err) 1195 } 1196 if err := validateTxPoolInternals(pool); err != nil { 1197 t.Fatalf("pool internal state corrupted: %v", err) 1198 } 1199 // Reprice the pool and check that underpriced transactions get dropped 1200 pool.SetGasPrice(big.NewInt(2)) 1201 1202 pending, queued = pool.Stats() 1203 if pending != 2 { 1204 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1205 } 1206 if queued != 5 { 1207 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) 1208 } 1209 if err := validateEvents(events, 0); err != nil { 1210 t.Fatalf("reprice event firing failed: %v", err) 1211 } 1212 if err := validateTxPoolInternals(pool); err != nil { 1213 t.Fatalf("pool internal state corrupted: %v", err) 1214 } 1215 // Check that we can't add the old transactions back 1216 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced { 1217 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1218 } 1219 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1220 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1221 } 1222 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); err != ErrUnderpriced { 1223 t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1224 } 1225 if err := validateEvents(events, 0); err != nil { 1226 t.Fatalf("post-reprice event firing failed: %v", err) 1227 } 1228 if err := validateTxPoolInternals(pool); err != nil { 1229 t.Fatalf("pool internal state corrupted: %v", err) 1230 } 1231 // However we can add local underpriced transactions 1232 tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3]) 1233 if err := pool.AddLocal(tx); err != nil { 1234 t.Fatalf("failed to add underpriced local transaction: %v", err) 1235 } 1236 if pending, _ = pool.Stats(); pending != 3 { 1237 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1238 } 1239 if err := validateEvents(events, 1); err != nil { 1240 t.Fatalf("post-reprice local event firing failed: %v", err) 1241 } 1242 if err := validateTxPoolInternals(pool); err != nil { 1243 t.Fatalf("pool internal state corrupted: %v", err) 1244 } 1245 // And we can fill gaps with properly priced transactions 1246 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil { 1247 t.Fatalf("failed to add pending transaction: %v", err) 1248 } 1249 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil { 1250 t.Fatalf("failed to add pending transaction: %v", err) 1251 } 1252 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil { 1253 t.Fatalf("failed to add queued transaction: %v", err) 1254 } 1255 if err := validateEvents(events, 5); err != nil { 1256 t.Fatalf("post-reprice event firing failed: %v", err) 1257 } 1258 if err := validateTxPoolInternals(pool); err != nil { 1259 t.Fatalf("pool internal state corrupted: %v", err) 1260 } 1261 } 1262 1263 // Tests that setting the transaction pool gas price to a higher value does not 1264 // remove local transactions. 1265 func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { 1266 t.Parallel() 1267 1268 // Create the pool to test the pricing enforcement with 1269 db, _ := ethdb.NewMemDatabase() 1270 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1271 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1272 1273 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1274 defer pool.Stop() 1275 1276 // Create a number of test accounts and fund them 1277 keys := make([]*ecdsa.PrivateKey, 3) 1278 for i := 0; i < len(keys); i++ { 1279 keys[i], _ = crypto.GenerateKey() 1280 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) 1281 } 1282 // Create transaction (both pending and queued) with a linearly growing gasprice 1283 for i := uint64(0); i < 500; i++ { 1284 // Add pending 1285 p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2]) 1286 if err := pool.AddLocal(p_tx); err != nil { 1287 t.Fatal(err) 1288 } 1289 // Add queued 1290 q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2]) 1291 if err := pool.AddLocal(q_tx); err != nil { 1292 t.Fatal(err) 1293 } 1294 } 1295 pending, queued := pool.Stats() 1296 expPending, expQueued := 500, 500 1297 validate := func() { 1298 pending, queued = pool.Stats() 1299 if pending != expPending { 1300 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) 1301 } 1302 if queued != expQueued { 1303 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) 1304 } 1305 1306 if err := validateTxPoolInternals(pool); err != nil { 1307 t.Fatalf("pool internal state corrupted: %v", err) 1308 } 1309 } 1310 validate() 1311 1312 // Reprice the pool and check that nothing is dropped 1313 pool.SetGasPrice(big.NewInt(2)) 1314 validate() 1315 1316 pool.SetGasPrice(big.NewInt(2)) 1317 pool.SetGasPrice(big.NewInt(4)) 1318 pool.SetGasPrice(big.NewInt(8)) 1319 pool.SetGasPrice(big.NewInt(100)) 1320 validate() 1321 } 1322 1323 // Tests that when the pool reaches its global transaction limit, underpriced 1324 // transactions are gradually shifted out for more expensive ones and any gapped 1325 // pending transactions are moved into the queue. 1326 // 1327 // Note, local transactions are never allowed to be dropped. 1328 func TestTransactionPoolUnderpricing(t *testing.T) { 1329 t.Parallel() 1330 1331 // Create the pool to test the pricing enforcement with 1332 db, _ := ethdb.NewMemDatabase() 1333 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1334 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1335 1336 config := testTxPoolConfig 1337 config.GlobalSlots = 2 1338 config.GlobalQueue = 2 1339 1340 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1341 defer pool.Stop() 1342 1343 // Keep track of transaction events to ensure all executables get announced 1344 events := make(chan TxPreEvent, 32) 1345 sub := pool.txFeed.Subscribe(events) 1346 defer sub.Unsubscribe() 1347 1348 // Create a number of test accounts and fund them 1349 keys := make([]*ecdsa.PrivateKey, 3) 1350 for i := 0; i < len(keys); i++ { 1351 keys[i], _ = crypto.GenerateKey() 1352 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1353 } 1354 // Generate and queue a batch of transactions, both pending and queued 1355 txs := types.Transactions{} 1356 1357 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) 1358 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) 1359 1360 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) 1361 1362 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) 1363 1364 // Import the batch and that both pending and queued transactions match up 1365 pool.AddRemotes(txs) 1366 pool.AddLocal(ltx) 1367 1368 pending, queued := pool.Stats() 1369 if pending != 3 { 1370 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1371 } 1372 if queued != 1 { 1373 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1374 } 1375 if err := validateEvents(events, 3); err != nil { 1376 t.Fatalf("original event firing failed: %v", err) 1377 } 1378 if err := validateTxPoolInternals(pool); err != nil { 1379 t.Fatalf("pool internal state corrupted: %v", err) 1380 } 1381 // Ensure that adding an underpriced transaction on block limit fails 1382 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1383 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1384 } 1385 // Ensure that adding high priced transactions drops cheap ones, but not own 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 - 1387 t.Fatalf("failed to add well priced transaction: %v", err) 1388 } 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 1390 t.Fatalf("failed to add well priced transaction: %v", err) 1391 } 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 1393 t.Fatalf("failed to add well priced transaction: %v", err) 1394 } 1395 pending, queued = pool.Stats() 1396 if pending != 2 { 1397 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1398 } 1399 if queued != 2 { 1400 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1401 } 1402 if err := validateEvents(events, 1); err != nil { 1403 t.Fatalf("additional event firing failed: %v", err) 1404 } 1405 if err := validateTxPoolInternals(pool); err != nil { 1406 t.Fatalf("pool internal state corrupted: %v", err) 1407 } 1408 // Ensure that adding local transactions can push out even higher priced ones 1409 tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2]) 1410 if err := pool.AddLocal(tx); err != nil { 1411 t.Fatalf("failed to add underpriced local transaction: %v", err) 1412 } 1413 pending, queued = pool.Stats() 1414 if pending != 2 { 1415 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1416 } 1417 if queued != 2 { 1418 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1419 } 1420 if err := validateEvents(events, 1); err != nil { 1421 t.Fatalf("local event firing failed: %v", err) 1422 } 1423 if err := validateTxPoolInternals(pool); err != nil { 1424 t.Fatalf("pool internal state corrupted: %v", err) 1425 } 1426 } 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 1496 // Tests that the pool rejects replacement transactions that don't meet the minimum 1497 // price bump required. 1498 func TestTransactionReplacement(t *testing.T) { 1499 t.Parallel() 1500 1501 // Create the pool to test the pricing enforcement with 1502 db, _ := ethdb.NewMemDatabase() 1503 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1504 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1505 1506 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1507 defer pool.Stop() 1508 1509 // Keep track of transaction events to ensure all executables get announced 1510 events := make(chan TxPreEvent, 32) 1511 sub := pool.txFeed.Subscribe(events) 1512 defer sub.Unsubscribe() 1513 1514 // Create a test account to add transactions with 1515 key, _ := crypto.GenerateKey() 1516 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1517 1518 // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1519 price := int64(100) 1520 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 1521 1522 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { 1523 t.Fatalf("failed to add original cheap pending transaction: %v", err) 1524 } 1525 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1526 t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1527 } 1528 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { 1529 t.Fatalf("failed to replace original cheap pending transaction: %v", err) 1530 } 1531 if err := validateEvents(events, 2); err != nil { 1532 t.Fatalf("cheap replacement event firing failed: %v", err) 1533 } 1534 1535 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { 1536 t.Fatalf("failed to add original proper pending transaction: %v", err) 1537 } 1538 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1539 t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1540 } 1541 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { 1542 t.Fatalf("failed to replace original proper pending transaction: %v", err) 1543 } 1544 if err := validateEvents(events, 2); err != nil { 1545 t.Fatalf("proper replacement event firing failed: %v", err) 1546 } 1547 // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1548 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { 1549 t.Fatalf("failed to add original cheap queued transaction: %v", err) 1550 } 1551 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1552 t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1553 } 1554 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { 1555 t.Fatalf("failed to replace original cheap queued transaction: %v", err) 1556 } 1557 1558 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { 1559 t.Fatalf("failed to add original proper queued transaction: %v", err) 1560 } 1561 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1562 t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1563 } 1564 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { 1565 t.Fatalf("failed to replace original proper queued transaction: %v", err) 1566 } 1567 1568 if err := validateEvents(events, 0); err != nil { 1569 t.Fatalf("queued replacement event firing failed: %v", err) 1570 } 1571 if err := validateTxPoolInternals(pool); err != nil { 1572 t.Fatalf("pool internal state corrupted: %v", err) 1573 } 1574 } 1575 1576 // Tests that local transactions are journaled to disk, but remote transactions 1577 // get discarded between restarts. 1578 func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } 1579 func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } 1580 1581 func testTransactionJournaling(t *testing.T, nolocals bool) { 1582 t.Parallel() 1583 1584 // Create a temporary file for the journal 1585 file, err := ioutil.TempFile("", "") 1586 if err != nil { 1587 t.Fatalf("failed to create temporary journal: %v", err) 1588 } 1589 journal := file.Name() 1590 defer os.Remove(journal) 1591 1592 // Clean up the temporary file, we only need the path for now 1593 file.Close() 1594 os.Remove(journal) 1595 1596 // Create the original pool to inject transaction into the journal 1597 db, _ := ethdb.NewMemDatabase() 1598 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1599 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1600 1601 config := testTxPoolConfig 1602 config.NoLocals = nolocals 1603 config.Journal = journal 1604 config.Rejournal = time.Second 1605 1606 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1607 1608 // Create two test accounts to ensure remotes expire but locals do not 1609 local, _ := crypto.GenerateKey() 1610 remote, _ := crypto.GenerateKey() 1611 1612 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1613 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1614 1615 // Add three local and a remote transactions and ensure they are queued up 1616 if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil { 1617 t.Fatalf("failed to add local transaction: %v", err) 1618 } 1619 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 1620 t.Fatalf("failed to add local transaction: %v", err) 1621 } 1622 if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { 1623 t.Fatalf("failed to add local transaction: %v", err) 1624 } 1625 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil { 1626 t.Fatalf("failed to add remote transaction: %v", err) 1627 } 1628 pending, queued := pool.Stats() 1629 if pending != 4 { 1630 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1631 } 1632 if queued != 0 { 1633 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1634 } 1635 if err := validateTxPoolInternals(pool); err != nil { 1636 t.Fatalf("pool internal state corrupted: %v", err) 1637 } 1638 // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive 1639 pool.Stop() 1640 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1641 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1642 1643 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1644 1645 pending, queued = pool.Stats() 1646 if queued != 0 { 1647 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1648 } 1649 if nolocals { 1650 if pending != 0 { 1651 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1652 } 1653 } else { 1654 if pending != 2 { 1655 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1656 } 1657 } 1658 if err := validateTxPoolInternals(pool); err != nil { 1659 t.Fatalf("pool internal state corrupted: %v", err) 1660 } 1661 // Bump the nonce temporarily and ensure the newly invalidated transaction is removed 1662 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) 1663 pool.lockedReset(nil, nil) 1664 time.Sleep(2 * config.Rejournal) 1665 pool.Stop() 1666 1667 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1668 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1669 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1670 1671 pending, queued = pool.Stats() 1672 if pending != 0 { 1673 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1674 } 1675 if nolocals { 1676 if queued != 0 { 1677 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1678 } 1679 } else { 1680 if queued != 1 { 1681 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1682 } 1683 } 1684 if err := validateTxPoolInternals(pool); err != nil { 1685 t.Fatalf("pool internal state corrupted: %v", err) 1686 } 1687 pool.Stop() 1688 } 1689 1690 // TestTransactionStatusCheck tests that the pool can correctly retrieve the 1691 // pending status of individual transactions. 1692 func TestTransactionStatusCheck(t *testing.T) { 1693 t.Parallel() 1694 1695 // Create the pool to test the status retrievals with 1696 db, _ := ethdb.NewMemDatabase() 1697 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1698 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1699 1700 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1701 defer pool.Stop() 1702 1703 // Create the test accounts to check various transaction statuses with 1704 keys := make([]*ecdsa.PrivateKey, 3) 1705 for i := 0; i < len(keys); i++ { 1706 keys[i], _ = crypto.GenerateKey() 1707 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1708 } 1709 // Generate and queue a batch of transactions, both pending and queued 1710 txs := types.Transactions{} 1711 1712 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only 1713 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued 1714 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) 1715 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only 1716 1717 // Import the transaction and ensure they are correctly added 1718 pool.AddRemotes(txs) 1719 1720 pending, queued := pool.Stats() 1721 if pending != 2 { 1722 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1723 } 1724 if queued != 2 { 1725 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1726 } 1727 if err := validateTxPoolInternals(pool); err != nil { 1728 t.Fatalf("pool internal state corrupted: %v", err) 1729 } 1730 // Retrieve the status of each transaction and validate them 1731 hashes := make([]common.Hash, len(txs)) 1732 for i, tx := range txs { 1733 hashes[i] = tx.Hash() 1734 } 1735 hashes = append(hashes, common.Hash{}) 1736 1737 statuses := pool.Status(hashes) 1738 expect := []TxStatus{TxStatusPending, TxStatusPending, TxStatusQueued, TxStatusQueued, TxStatusUnknown} 1739 1740 for i := 0; i < len(statuses); i++ { 1741 if statuses[i] != expect[i] { 1742 t.Errorf("transaction %d: status mismatch: have %v, want %v", i, statuses[i], expect[i]) 1743 } 1744 } 1745 } 1746 1747 // Benchmarks the speed of validating the contents of the pending queue of the 1748 // transaction pool. 1749 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 1750 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 1751 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 1752 1753 func benchmarkPendingDemotion(b *testing.B, size int) { 1754 // Add a batch of transactions to a pool one by one 1755 pool, key := setupTxPool() 1756 defer pool.Stop() 1757 1758 account, _ := deriveSender(transaction(0, 0, key)) 1759 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1760 1761 for i := 0; i < size; i++ { 1762 tx := transaction(uint64(i), 100000, key) 1763 pool.promoteTx(account, tx.Hash(), tx) 1764 } 1765 // Benchmark the speed of pool validation 1766 b.ResetTimer() 1767 for i := 0; i < b.N; i++ { 1768 pool.demoteUnexecutables() 1769 } 1770 } 1771 1772 // Benchmarks the speed of scheduling the contents of the future queue of the 1773 // transaction pool. 1774 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 1775 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 1776 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 1777 1778 func benchmarkFuturePromotion(b *testing.B, size int) { 1779 // Add a batch of transactions to a pool one by one 1780 pool, key := setupTxPool() 1781 defer pool.Stop() 1782 1783 account, _ := deriveSender(transaction(0, 0, key)) 1784 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1785 1786 for i := 0; i < size; i++ { 1787 tx := transaction(uint64(1+i), 100000, key) 1788 pool.enqueueTx(tx.Hash(), tx) 1789 } 1790 // Benchmark the speed of pool validation 1791 b.ResetTimer() 1792 for i := 0; i < b.N; i++ { 1793 pool.promoteExecutables(nil) 1794 } 1795 } 1796 1797 // Benchmarks the speed of iterative transaction insertion. 1798 func BenchmarkPoolInsert(b *testing.B) { 1799 // Generate a batch of transactions to enqueue into the pool 1800 pool, key := setupTxPool() 1801 defer pool.Stop() 1802 1803 account, _ := deriveSender(transaction(0, 0, key)) 1804 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1805 1806 txs := make(types.Transactions, b.N) 1807 for i := 0; i < b.N; i++ { 1808 txs[i] = transaction(uint64(i), 100000, key) 1809 } 1810 // Benchmark importing the transactions into the queue 1811 b.ResetTimer() 1812 for _, tx := range txs { 1813 pool.AddRemote(tx) 1814 } 1815 } 1816 1817 // Benchmarks the speed of batched transaction insertion. 1818 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 1819 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 1820 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 1821 1822 func benchmarkPoolBatchInsert(b *testing.B, size int) { 1823 // Generate a batch of transactions to enqueue into the pool 1824 pool, key := setupTxPool() 1825 defer pool.Stop() 1826 1827 account, _ := deriveSender(transaction(0, 0, key)) 1828 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1829 1830 batches := make([]types.Transactions, b.N) 1831 for i := 0; i < b.N; i++ { 1832 batches[i] = make(types.Transactions, size) 1833 for j := 0; j < size; j++ { 1834 batches[i][j] = transaction(uint64(size*i+j), 100000, key) 1835 } 1836 } 1837 // Benchmark importing the transactions into the queue 1838 b.ResetTimer() 1839 for _, batch := range batches { 1840 pool.AddRemotes(batch) 1841 } 1842 }