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