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