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