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