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