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