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