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