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