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