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