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