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