github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/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 "fmt" 22 "io/ioutil" 23 "math/big" 24 "math/rand" 25 "os" 26 "testing" 27 "time" 28 29 "github.com/ethereum-optimism/optimism/l2geth/common" 30 "github.com/ethereum-optimism/optimism/l2geth/core/rawdb" 31 "github.com/ethereum-optimism/optimism/l2geth/core/state" 32 "github.com/ethereum-optimism/optimism/l2geth/core/types" 33 "github.com/ethereum-optimism/optimism/l2geth/crypto" 34 "github.com/ethereum-optimism/optimism/l2geth/event" 35 "github.com/ethereum-optimism/optimism/l2geth/params" 36 ) 37 38 // testTxPoolConfig is a transaction pool configuration without stateful disk 39 // sideeffects used during testing. 40 var testTxPoolConfig TxPoolConfig 41 42 func init() { 43 testTxPoolConfig = DefaultTxPoolConfig 44 testTxPoolConfig.Journal = "" 45 } 46 47 type testBlockChain struct { 48 statedb *state.StateDB 49 gasLimit uint64 50 chainHeadFeed *event.Feed 51 } 52 53 func (bc *testBlockChain) CurrentBlock() *types.Block { 54 return types.NewBlock(&types.Header{ 55 GasLimit: bc.gasLimit, 56 }, nil, nil, nil) 57 } 58 59 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 60 return bc.CurrentBlock() 61 } 62 63 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 64 return bc.statedb, nil 65 } 66 67 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 68 return bc.chainHeadFeed.Subscribe(ch) 69 } 70 71 func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction { 72 return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) 73 } 74 75 func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 76 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) 77 return tx 78 } 79 80 func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { 81 data := make([]byte, bytes) 82 rand.Read(data) 83 84 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) 85 return tx 86 } 87 88 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 89 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 90 blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} 91 92 key, _ := crypto.GenerateKey() 93 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 94 95 return pool, key 96 } 97 98 // validateTxPoolInternals checks various consistency invariants within the pool. 99 func validateTxPoolInternals(pool *TxPool) error { 100 pool.mu.RLock() 101 defer pool.mu.RUnlock() 102 103 // Ensure the total transaction set is consistent with pending + queued 104 pending, queued := pool.stats() 105 if total := pool.all.Count(); total != pending+queued { 106 return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) 107 } 108 if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { 109 return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued) 110 } 111 // Ensure the next nonce to assign is the correct one 112 for addr, txs := range pool.pending { 113 // Find the last transaction 114 var last uint64 115 for nonce := range txs.txs.items { 116 if last < nonce { 117 last = nonce 118 } 119 } 120 if nonce := pool.Nonce(addr); nonce != last+1 { 121 return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) 122 } 123 } 124 return nil 125 } 126 127 // validateEvents checks that the correct number of transaction addition events 128 // were fired on the pool's event feed. 129 func validateEvents(events chan NewTxsEvent, count int) error { 130 var received []*types.Transaction 131 132 for len(received) < count { 133 select { 134 case ev := <-events: 135 received = append(received, ev.Txs...) 136 case <-time.After(time.Second): 137 return fmt.Errorf("event #%d not fired", len(received)) 138 } 139 } 140 if len(received) > count { 141 return fmt.Errorf("more than %d events fired: %v", count, received[count:]) 142 } 143 select { 144 case ev := <-events: 145 return fmt.Errorf("more than %d events fired: %v", count, ev.Txs) 146 147 case <-time.After(50 * time.Millisecond): 148 // This branch should be "default", but it's a data race between goroutines, 149 // reading the event channel and pushing into it, so better wait a bit ensuring 150 // really nothing gets injected. 151 } 152 return nil 153 } 154 155 func deriveSender(tx *types.Transaction) (common.Address, error) { 156 return types.Sender(types.HomesteadSigner{}, tx) 157 } 158 159 type testChain struct { 160 *testBlockChain 161 address common.Address 162 trigger *bool 163 } 164 165 // testChain.State() is used multiple times to reset the pending state. 166 // when simulate is true it will create a state that indicates 167 // that tx0 and tx1 are included in the chain. 168 func (c *testChain) State() (*state.StateDB, error) { 169 // delay "state change" by one. The tx pool fetches the 170 // state multiple times and by delaying it a bit we simulate 171 // a state change between those fetches. 172 stdb := c.statedb 173 if *c.trigger { 174 c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 175 // simulate that the new head block included tx0 and tx1 176 c.statedb.SetNonce(c.address, 2) 177 c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether)) 178 *c.trigger = false 179 } 180 return stdb, nil 181 } 182 183 // This test simulates a scenario where a new block is imported during a 184 // state reset and tests whether the pending state is in sync with the 185 // block head event that initiated the resetState(). 186 func TestStateChangeDuringTransactionPoolReset(t *testing.T) { 187 t.Parallel() 188 189 var ( 190 key, _ = crypto.GenerateKey() 191 address = crypto.PubkeyToAddress(key.PublicKey) 192 statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 193 trigger = false 194 ) 195 196 // setup pool with 2 transaction in it 197 statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) 198 blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger} 199 200 tx0 := transaction(0, 100000, key) 201 tx1 := transaction(1, 100000, key) 202 203 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 204 defer pool.Stop() 205 206 nonce := pool.Nonce(address) 207 if nonce != 0 { 208 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 209 } 210 211 pool.AddRemotesSync([]*types.Transaction{tx0, tx1}) 212 213 nonce = pool.Nonce(address) 214 if nonce != 2 { 215 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 216 } 217 218 // trigger state change in the background 219 trigger = true 220 <-pool.requestReset(nil, nil) 221 222 _, err := pool.Pending() 223 if err != nil { 224 t.Fatalf("Could not fetch pending transactions: %v", err) 225 } 226 nonce = pool.Nonce(address) 227 if nonce != 2 { 228 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 229 } 230 } 231 232 func TestInvalidTransactions(t *testing.T) { 233 t.Parallel() 234 235 pool, key := setupTxPool() 236 defer pool.Stop() 237 238 tx := transaction(0, 100, key) 239 from, _ := deriveSender(tx) 240 241 pool.currentState.AddBalance(from, big.NewInt(1)) 242 if err := pool.AddRemote(tx); err != ErrInsufficientFunds { 243 t.Error("expected", ErrInsufficientFunds) 244 } 245 246 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) 247 pool.currentState.AddBalance(from, balance) 248 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 249 t.Error("expected", ErrIntrinsicGas, "got", err) 250 } 251 252 pool.currentState.SetNonce(from, 1) 253 pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) 254 tx = transaction(0, 100000, key) 255 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 256 t.Error("expected", ErrNonceTooLow) 257 } 258 259 tx = transaction(1, 100000, key) 260 pool.gasPrice = big.NewInt(1000) 261 if err := pool.AddRemote(tx); err != ErrUnderpriced { 262 t.Error("expected", ErrUnderpriced, "got", err) 263 } 264 if err := pool.AddLocal(tx); err != nil { 265 t.Error("expected", nil, "got", err) 266 } 267 } 268 269 func TestTransactionQueue(t *testing.T) { 270 t.Parallel() 271 272 pool, key := setupTxPool() 273 defer pool.Stop() 274 275 tx := transaction(0, 100, key) 276 from, _ := deriveSender(tx) 277 pool.currentState.AddBalance(from, big.NewInt(1000)) 278 <-pool.requestReset(nil, nil) 279 280 pool.enqueueTx(tx.Hash(), tx) 281 <-pool.requestPromoteExecutables(newAccountSet(pool.signer, from)) 282 if len(pool.pending) != 1 { 283 t.Error("expected valid txs to be 1 is", len(pool.pending)) 284 } 285 286 tx = transaction(1, 100, key) 287 from, _ = deriveSender(tx) 288 pool.currentState.SetNonce(from, 2) 289 pool.enqueueTx(tx.Hash(), tx) 290 291 <-pool.requestPromoteExecutables(newAccountSet(pool.signer, from)) 292 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 293 t.Error("expected transaction to be in tx pool") 294 } 295 if len(pool.queue) > 0 { 296 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 297 } 298 } 299 300 func TestTransactionQueue2(t *testing.T) { 301 t.Parallel() 302 303 pool, key := setupTxPool() 304 defer pool.Stop() 305 306 tx1 := transaction(0, 100, key) 307 tx2 := transaction(10, 100, key) 308 tx3 := transaction(11, 100, key) 309 from, _ := deriveSender(tx1) 310 pool.currentState.AddBalance(from, big.NewInt(1000)) 311 pool.reset(nil, nil) 312 313 pool.enqueueTx(tx1.Hash(), tx1) 314 pool.enqueueTx(tx2.Hash(), tx2) 315 pool.enqueueTx(tx3.Hash(), tx3) 316 317 pool.promoteExecutables([]common.Address{from}) 318 if len(pool.pending) != 1 { 319 t.Error("expected pending length to be 1, got", len(pool.pending)) 320 } 321 if pool.queue[from].Len() != 2 { 322 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 323 } 324 } 325 326 func TestTransactionNegativeValue(t *testing.T) { 327 t.Parallel() 328 329 pool, key := setupTxPool() 330 defer pool.Stop() 331 332 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) 333 from, _ := deriveSender(tx) 334 pool.currentState.AddBalance(from, big.NewInt(1)) 335 if err := pool.AddRemote(tx); err != ErrNegativeValue { 336 t.Error("expected", ErrNegativeValue, "got", err) 337 } 338 } 339 340 func TestTransactionChainFork(t *testing.T) { 341 t.Parallel() 342 343 pool, key := setupTxPool() 344 defer pool.Stop() 345 346 addr := crypto.PubkeyToAddress(key.PublicKey) 347 resetState := func() { 348 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 349 statedb.AddBalance(addr, big.NewInt(100000000000000)) 350 351 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 352 <-pool.requestReset(nil, nil) 353 } 354 resetState() 355 356 tx := transaction(0, 100000, key) 357 if _, err := pool.add(tx, false); err != nil { 358 t.Error("didn't expect error", err) 359 } 360 pool.removeTx(tx.Hash(), true) 361 362 // reset the pool's internal state 363 resetState() 364 if _, err := pool.add(tx, false); err != nil { 365 t.Error("didn't expect error", err) 366 } 367 } 368 369 func TestTransactionDoubleNonce(t *testing.T) { 370 t.Parallel() 371 372 pool, key := setupTxPool() 373 defer pool.Stop() 374 375 addr := crypto.PubkeyToAddress(key.PublicKey) 376 resetState := func() { 377 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 378 statedb.AddBalance(addr, big.NewInt(100000000000000)) 379 380 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 381 <-pool.requestReset(nil, nil) 382 } 383 resetState() 384 385 signer := types.HomesteadSigner{} 386 tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key) 387 tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key) 388 tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) 389 390 // Add the first two transaction, ensure higher priced stays only 391 if replace, err := pool.add(tx1, false); err != nil || replace { 392 t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) 393 } 394 if replace, err := pool.add(tx2, false); err != nil || !replace { 395 t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) 396 } 397 <-pool.requestPromoteExecutables(newAccountSet(signer, addr)) 398 if pool.pending[addr].Len() != 1 { 399 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 400 } 401 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 402 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 403 } 404 405 // Add the third transaction and ensure it's not saved (smaller price) 406 pool.add(tx3, false) 407 <-pool.requestPromoteExecutables(newAccountSet(signer, addr)) 408 if pool.pending[addr].Len() != 1 { 409 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 410 } 411 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 412 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 413 } 414 // Ensure the total transaction count is correct 415 if pool.all.Count() != 1 { 416 t.Error("expected 1 total transactions, got", pool.all.Count()) 417 } 418 } 419 420 func TestTransactionMissingNonce(t *testing.T) { 421 t.Parallel() 422 423 pool, key := setupTxPool() 424 defer pool.Stop() 425 426 addr := crypto.PubkeyToAddress(key.PublicKey) 427 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 428 tx := transaction(1, 100000, key) 429 if _, err := pool.add(tx, false); err != nil { 430 t.Error("didn't expect error", err) 431 } 432 if len(pool.pending) != 0 { 433 t.Error("expected 0 pending transactions, got", len(pool.pending)) 434 } 435 if pool.queue[addr].Len() != 1 { 436 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 437 } 438 if pool.all.Count() != 1 { 439 t.Error("expected 1 total transactions, got", pool.all.Count()) 440 } 441 } 442 443 func TestTransactionNonceRecovery(t *testing.T) { 444 t.Parallel() 445 446 const n = 10 447 pool, key := setupTxPool() 448 defer pool.Stop() 449 450 addr := crypto.PubkeyToAddress(key.PublicKey) 451 pool.currentState.SetNonce(addr, n) 452 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 453 <-pool.requestReset(nil, nil) 454 455 tx := transaction(n, 100000, key) 456 if err := pool.AddRemote(tx); err != nil { 457 t.Error(err) 458 } 459 // simulate some weird re-order of transactions and missing nonce(s) 460 pool.currentState.SetNonce(addr, n-1) 461 <-pool.requestReset(nil, nil) 462 if fn := pool.Nonce(addr); fn != n-1 { 463 t.Errorf("expected nonce to be %d, got %d", n-1, fn) 464 } 465 } 466 467 // Tests that if an account runs out of funds, any pending and queued transactions 468 // are dropped. 469 func TestTransactionDropping(t *testing.T) { 470 t.Parallel() 471 472 // Create a test account and fund it 473 pool, key := setupTxPool() 474 defer pool.Stop() 475 476 account := crypto.PubkeyToAddress(key.PublicKey) 477 pool.currentState.AddBalance(account, big.NewInt(1000)) 478 479 // Add some pending and some queued transactions 480 var ( 481 tx0 = transaction(0, 100, key) 482 tx1 = transaction(1, 200, key) 483 tx2 = transaction(2, 300, key) 484 tx10 = transaction(10, 100, key) 485 tx11 = transaction(11, 200, key) 486 tx12 = transaction(12, 300, key) 487 ) 488 pool.promoteTx(account, tx0.Hash(), tx0) 489 pool.promoteTx(account, tx1.Hash(), tx1) 490 pool.promoteTx(account, tx2.Hash(), tx2) 491 pool.enqueueTx(tx10.Hash(), tx10) 492 pool.enqueueTx(tx11.Hash(), tx11) 493 pool.enqueueTx(tx12.Hash(), tx12) 494 495 // Check that pre and post validations leave the pool as is 496 if pool.pending[account].Len() != 3 { 497 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 498 } 499 if pool.queue[account].Len() != 3 { 500 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 501 } 502 if pool.all.Count() != 6 { 503 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) 504 } 505 <-pool.requestReset(nil, nil) 506 if pool.pending[account].Len() != 3 { 507 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 508 } 509 if pool.queue[account].Len() != 3 { 510 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 511 } 512 if pool.all.Count() != 6 { 513 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 6) 514 } 515 // Reduce the balance of the account, and check that invalidated transactions are dropped 516 pool.currentState.AddBalance(account, big.NewInt(-650)) 517 <-pool.requestReset(nil, nil) 518 519 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 520 t.Errorf("funded pending transaction missing: %v", tx0) 521 } 522 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { 523 t.Errorf("funded pending transaction missing: %v", tx0) 524 } 525 if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { 526 t.Errorf("out-of-fund pending transaction present: %v", tx1) 527 } 528 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 529 t.Errorf("funded queued transaction missing: %v", tx10) 530 } 531 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { 532 t.Errorf("funded queued transaction missing: %v", tx10) 533 } 534 if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { 535 t.Errorf("out-of-fund queued transaction present: %v", tx11) 536 } 537 if pool.all.Count() != 4 { 538 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 4) 539 } 540 // Reduce the block gas limit, check that invalidated transactions are dropped 541 pool.chain.(*testBlockChain).gasLimit = 100 542 <-pool.requestReset(nil, nil) 543 544 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 545 t.Errorf("funded pending transaction missing: %v", tx0) 546 } 547 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { 548 t.Errorf("over-gased pending transaction present: %v", tx1) 549 } 550 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 551 t.Errorf("funded queued transaction missing: %v", tx10) 552 } 553 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { 554 t.Errorf("over-gased queued transaction present: %v", tx11) 555 } 556 if pool.all.Count() != 2 { 557 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 2) 558 } 559 } 560 561 // Tests that if a transaction is dropped from the current pending pool (e.g. out 562 // of fund), all consecutive (still valid, but not executable) transactions are 563 // postponed back into the future queue to prevent broadcasting them. 564 func TestTransactionPostponing(t *testing.T) { 565 t.Parallel() 566 567 // Create the pool to test the postponing with 568 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 569 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 570 571 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 572 defer pool.Stop() 573 574 // Create two test accounts to produce different gap profiles with 575 keys := make([]*ecdsa.PrivateKey, 2) 576 accs := make([]common.Address, len(keys)) 577 578 for i := 0; i < len(keys); i++ { 579 keys[i], _ = crypto.GenerateKey() 580 accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 581 582 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100)) 583 } 584 // Add a batch consecutive pending transactions for validation 585 txs := []*types.Transaction{} 586 for i, key := range keys { 587 588 for j := 0; j < 100; j++ { 589 var tx *types.Transaction 590 if (i+j)%2 == 0 { 591 tx = transaction(uint64(j), 25000, key) 592 } else { 593 tx = transaction(uint64(j), 50000, key) 594 } 595 txs = append(txs, tx) 596 } 597 } 598 for i, err := range pool.AddRemotesSync(txs) { 599 if err != nil { 600 t.Fatalf("tx %d: failed to add transactions: %v", i, err) 601 } 602 } 603 // Check that pre and post validations leave the pool as is 604 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 605 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 606 } 607 if len(pool.queue) != 0 { 608 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 609 } 610 if pool.all.Count() != len(txs) { 611 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) 612 } 613 <-pool.requestReset(nil, nil) 614 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 615 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 616 } 617 if len(pool.queue) != 0 { 618 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 619 } 620 if pool.all.Count() != len(txs) { 621 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)) 622 } 623 // Reduce the balance of the account, and check that transactions are reorganised 624 for _, addr := range accs { 625 pool.currentState.AddBalance(addr, big.NewInt(-1)) 626 } 627 <-pool.requestReset(nil, nil) 628 629 // The first account's first transaction remains valid, check that subsequent 630 // ones are either filtered out, or queued up for later. 631 if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok { 632 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0]) 633 } 634 if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok { 635 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0]) 636 } 637 for i, tx := range txs[1:100] { 638 if i%2 == 1 { 639 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 640 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 641 } 642 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok { 643 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 644 } 645 } else { 646 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 647 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 648 } 649 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok { 650 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 651 } 652 } 653 } 654 // The second account's first transaction got invalid, check that all transactions 655 // are either filtered out, or queued up for later. 656 if pool.pending[accs[1]] != nil { 657 t.Errorf("invalidated account still has pending transactions") 658 } 659 for i, tx := range txs[100:] { 660 if i%2 == 1 { 661 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok { 662 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx) 663 } 664 } else { 665 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok { 666 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx) 667 } 668 } 669 } 670 if pool.all.Count() != len(txs)/2 { 671 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), len(txs)/2) 672 } 673 } 674 675 // Tests that if the transaction pool has both executable and non-executable 676 // transactions from an origin account, filling the nonce gap moves all queued 677 // ones into the pending pool. 678 func TestTransactionGapFilling(t *testing.T) { 679 t.Parallel() 680 681 // Create a test account and fund it 682 pool, key := setupTxPool() 683 defer pool.Stop() 684 685 account := crypto.PubkeyToAddress(key.PublicKey) 686 pool.currentState.AddBalance(account, big.NewInt(1000000)) 687 688 // Keep track of transaction events to ensure all executables get announced 689 events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) 690 sub := pool.txFeed.Subscribe(events) 691 defer sub.Unsubscribe() 692 693 // Create a pending and a queued transaction with a nonce-gap in between 694 pool.AddRemotesSync([]*types.Transaction{ 695 transaction(0, 100000, key), 696 transaction(2, 100000, key), 697 }) 698 pending, queued := pool.Stats() 699 if pending != 1 { 700 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) 701 } 702 if queued != 1 { 703 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 704 } 705 if err := validateEvents(events, 1); err != nil { 706 t.Fatalf("original event firing failed: %v", err) 707 } 708 if err := validateTxPoolInternals(pool); err != nil { 709 t.Fatalf("pool internal state corrupted: %v", err) 710 } 711 // Fill the nonce gap and ensure all transactions become pending 712 if err := pool.addRemoteSync(transaction(1, 100000, key)); err != nil { 713 t.Fatalf("failed to add gapped transaction: %v", err) 714 } 715 pending, queued = pool.Stats() 716 if pending != 3 { 717 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 718 } 719 if queued != 0 { 720 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 721 } 722 if err := validateEvents(events, 2); err != nil { 723 t.Fatalf("gap-filling event firing failed: %v", err) 724 } 725 if err := validateTxPoolInternals(pool); err != nil { 726 t.Fatalf("pool internal state corrupted: %v", err) 727 } 728 } 729 730 // Tests that if the transaction count belonging to a single account goes above 731 // some threshold, the higher transactions are dropped to prevent DOS attacks. 732 func TestTransactionQueueAccountLimiting(t *testing.T) { 733 t.Parallel() 734 735 // Create a test account and fund it 736 pool, key := setupTxPool() 737 defer pool.Stop() 738 739 account := crypto.PubkeyToAddress(key.PublicKey) 740 pool.currentState.AddBalance(account, big.NewInt(1000000)) 741 742 // Keep queuing up transactions and make sure all above a limit are dropped 743 for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { 744 if err := pool.addRemoteSync(transaction(i, 100000, key)); err != nil { 745 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 746 } 747 if len(pool.pending) != 0 { 748 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 749 } 750 if i <= testTxPoolConfig.AccountQueue { 751 if pool.queue[account].Len() != int(i) { 752 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 753 } 754 } else { 755 if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) { 756 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue) 757 } 758 } 759 } 760 if pool.all.Count() != int(testTxPoolConfig.AccountQueue) { 761 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue) 762 } 763 } 764 765 // Tests that if the transaction count belonging to multiple accounts go above 766 // some threshold, the higher transactions are dropped to prevent DOS attacks. 767 // 768 // This logic should not hold for local transactions, unless the local tracking 769 // mechanism is disabled. 770 func TestTransactionQueueGlobalLimiting(t *testing.T) { 771 testTransactionQueueGlobalLimiting(t, false) 772 } 773 func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { 774 testTransactionQueueGlobalLimiting(t, true) 775 } 776 777 func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { 778 t.Parallel() 779 780 // Create the pool to test the limit enforcement with 781 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 782 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 783 784 config := testTxPoolConfig 785 config.NoLocals = nolocals 786 config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) 787 788 pool := NewTxPool(config, params.TestChainConfig, blockchain) 789 defer pool.Stop() 790 791 // Create a number of test accounts and fund them (last one will be the local) 792 keys := make([]*ecdsa.PrivateKey, 5) 793 for i := 0; i < len(keys); i++ { 794 keys[i], _ = crypto.GenerateKey() 795 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 796 } 797 local := keys[len(keys)-1] 798 799 // Generate and queue a batch of transactions 800 nonces := make(map[common.Address]uint64) 801 802 txs := make(types.Transactions, 0, 3*config.GlobalQueue) 803 for len(txs) < cap(txs) { 804 key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account 805 addr := crypto.PubkeyToAddress(key.PublicKey) 806 807 txs = append(txs, transaction(nonces[addr]+1, 100000, key)) 808 nonces[addr]++ 809 } 810 // Import the batch and verify that limits have been enforced 811 pool.AddRemotesSync(txs) 812 813 queued := 0 814 for addr, list := range pool.queue { 815 if list.Len() > int(config.AccountQueue) { 816 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 817 } 818 queued += list.Len() 819 } 820 if queued > int(config.GlobalQueue) { 821 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 822 } 823 // Generate a batch of transactions from the local account and import them 824 txs = txs[:0] 825 for i := uint64(0); i < 3*config.GlobalQueue; i++ { 826 txs = append(txs, transaction(i+1, 100000, local)) 827 } 828 pool.AddLocals(txs) 829 830 // If locals are disabled, the previous eviction algorithm should apply here too 831 if nolocals { 832 queued := 0 833 for addr, list := range pool.queue { 834 if list.Len() > int(config.AccountQueue) { 835 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 836 } 837 queued += list.Len() 838 } 839 if queued > int(config.GlobalQueue) { 840 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 841 } 842 } else { 843 // Local exemptions are enabled, make sure the local account owned the queue 844 if len(pool.queue) != 1 { 845 t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) 846 } 847 // Also ensure no local transactions are ever dropped, even if above global limits 848 if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { 849 t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) 850 } 851 } 852 } 853 854 // Tests that if an account remains idle for a prolonged amount of time, any 855 // non-executable transactions queued up are dropped to prevent wasting resources 856 // on shuffling them around. 857 // 858 // This logic should not hold for local transactions, unless the local tracking 859 // mechanism is disabled. 860 func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) } 861 func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { 862 testTransactionQueueTimeLimiting(t, true) 863 } 864 865 func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { 866 // Reduce the eviction interval to a testable amount 867 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 868 evictionInterval = time.Second 869 870 // Create the pool to test the non-expiration enforcement 871 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 872 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 873 874 config := testTxPoolConfig 875 config.Lifetime = time.Second 876 config.NoLocals = nolocals 877 878 pool := NewTxPool(config, params.TestChainConfig, blockchain) 879 defer pool.Stop() 880 881 // Create two test accounts to ensure remotes expire but locals do not 882 local, _ := crypto.GenerateKey() 883 remote, _ := crypto.GenerateKey() 884 885 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 886 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 887 888 // Add the two transactions and ensure they both are queued up 889 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 890 t.Fatalf("failed to add local transaction: %v", err) 891 } 892 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { 893 t.Fatalf("failed to add remote transaction: %v", err) 894 } 895 pending, queued := pool.Stats() 896 if pending != 0 { 897 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 898 } 899 if queued != 2 { 900 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 901 } 902 if err := validateTxPoolInternals(pool); err != nil { 903 t.Fatalf("pool internal state corrupted: %v", err) 904 } 905 // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains 906 time.Sleep(2 * config.Lifetime) 907 908 pending, queued = pool.Stats() 909 if pending != 0 { 910 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 911 } 912 if nolocals { 913 if queued != 0 { 914 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 915 } 916 } else { 917 if queued != 1 { 918 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 919 } 920 } 921 if err := validateTxPoolInternals(pool); err != nil { 922 t.Fatalf("pool internal state corrupted: %v", err) 923 } 924 } 925 926 // Tests that even if the transaction count belonging to a single account goes 927 // above some threshold, as long as the transactions are executable, they are 928 // accepted. 929 func TestTransactionPendingLimiting(t *testing.T) { 930 t.Parallel() 931 932 // Create a test account and fund it 933 pool, key := setupTxPool() 934 defer pool.Stop() 935 936 account := crypto.PubkeyToAddress(key.PublicKey) 937 pool.currentState.AddBalance(account, big.NewInt(1000000)) 938 939 // Keep track of transaction events to ensure all executables get announced 940 events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) 941 sub := pool.txFeed.Subscribe(events) 942 defer sub.Unsubscribe() 943 944 // Keep queuing up transactions and make sure all above a limit are dropped 945 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 946 if err := pool.addRemoteSync(transaction(i, 100000, key)); err != nil { 947 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 948 } 949 if pool.pending[account].Len() != int(i)+1 { 950 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 951 } 952 if len(pool.queue) != 0 { 953 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 954 } 955 } 956 if pool.all.Count() != int(testTxPoolConfig.AccountQueue+5) { 957 t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), testTxPoolConfig.AccountQueue+5) 958 } 959 if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { 960 t.Fatalf("event firing failed: %v", err) 961 } 962 if err := validateTxPoolInternals(pool); err != nil { 963 t.Fatalf("pool internal state corrupted: %v", err) 964 } 965 } 966 967 // Tests that if the transaction count belonging to multiple accounts go above 968 // some hard threshold, the higher transactions are dropped to prevent DOS 969 // attacks. 970 func TestTransactionPendingGlobalLimiting(t *testing.T) { 971 t.Parallel() 972 973 // Create the pool to test the limit enforcement with 974 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 975 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 976 977 config := testTxPoolConfig 978 config.GlobalSlots = config.AccountSlots * 10 979 980 pool := NewTxPool(config, params.TestChainConfig, blockchain) 981 defer pool.Stop() 982 983 // Create a number of test accounts and fund them 984 keys := make([]*ecdsa.PrivateKey, 5) 985 for i := 0; i < len(keys); i++ { 986 keys[i], _ = crypto.GenerateKey() 987 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 988 } 989 // Generate and queue a batch of transactions 990 nonces := make(map[common.Address]uint64) 991 992 txs := types.Transactions{} 993 for _, key := range keys { 994 addr := crypto.PubkeyToAddress(key.PublicKey) 995 for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { 996 txs = append(txs, transaction(nonces[addr], 100000, key)) 997 nonces[addr]++ 998 } 999 } 1000 // Import the batch and verify that limits have been enforced 1001 pool.AddRemotesSync(txs) 1002 1003 pending := 0 1004 for _, list := range pool.pending { 1005 pending += list.Len() 1006 } 1007 if pending > int(config.GlobalSlots) { 1008 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) 1009 } 1010 if err := validateTxPoolInternals(pool); err != nil { 1011 t.Fatalf("pool internal state corrupted: %v", err) 1012 } 1013 } 1014 1015 // Test the limit on transaction size is enforced correctly. 1016 // This test verifies every transaction having allowed size 1017 // is added to the pool, and longer transactions are rejected. 1018 func TestTransactionAllowedTxSize(t *testing.T) { 1019 t.Parallel() 1020 1021 // Create a test account and fund it 1022 pool, key := setupTxPool() 1023 defer pool.Stop() 1024 1025 account := crypto.PubkeyToAddress(key.PublicKey) 1026 pool.currentState.AddBalance(account, big.NewInt(1000000000)) 1027 1028 // Compute maximal data size for transactions (lower bound). 1029 // 1030 // It is assumed the fields in the transaction (except of the data) are: 1031 // - nonce <= 32 bytes 1032 // - gasPrice <= 32 bytes 1033 // - gasLimit <= 32 bytes 1034 // - recipient == 20 bytes 1035 // - value <= 32 bytes 1036 // - signature == 65 bytes 1037 // All those fields are summed up to at most 213 bytes. 1038 baseSize := uint64(213) 1039 dataSize := txMaxSize - baseSize 1040 1041 // Try adding a transaction with maximal allowed size 1042 tx := pricedDataTransaction(0, pool.currentMaxGas, big.NewInt(1), key, dataSize) 1043 if err := pool.addRemoteSync(tx); err != nil { 1044 t.Fatalf("failed to add transaction of size %d, close to maximal: %v", int(tx.Size()), err) 1045 } 1046 // Try adding a transaction with random allowed size 1047 if err := pool.addRemoteSync(pricedDataTransaction(1, pool.currentMaxGas, big.NewInt(1), key, uint64(rand.Intn(int(dataSize))))); err != nil { 1048 t.Fatalf("failed to add transaction of random allowed size: %v", err) 1049 } 1050 // Try adding a transaction of minimal not allowed size 1051 if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentMaxGas, big.NewInt(1), key, txMaxSize)); err == nil { 1052 t.Fatalf("expected rejection on slightly oversize transaction") 1053 } 1054 // Try adding a transaction of random not allowed size 1055 if err := pool.addRemoteSync(pricedDataTransaction(2, pool.currentMaxGas, big.NewInt(1), key, dataSize+1+uint64(rand.Intn(int(10*txMaxSize))))); err == nil { 1056 t.Fatalf("expected rejection on oversize transaction") 1057 } 1058 // Run some sanity checks on the pool internals 1059 pending, queued := pool.Stats() 1060 if pending != 2 { 1061 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1062 } 1063 if queued != 0 { 1064 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1065 } 1066 if err := validateTxPoolInternals(pool); err != nil { 1067 t.Fatalf("pool internal state corrupted: %v", err) 1068 } 1069 } 1070 1071 // Tests that if transactions start being capped, transactions are also removed from 'all' 1072 func TestTransactionCapClearsFromAll(t *testing.T) { 1073 t.Parallel() 1074 1075 // Create the pool to test the limit enforcement with 1076 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1077 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1078 1079 config := testTxPoolConfig 1080 config.AccountSlots = 2 1081 config.AccountQueue = 2 1082 config.GlobalSlots = 8 1083 1084 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1085 defer pool.Stop() 1086 1087 // Create a number of test accounts and fund them 1088 key, _ := crypto.GenerateKey() 1089 addr := crypto.PubkeyToAddress(key.PublicKey) 1090 pool.currentState.AddBalance(addr, big.NewInt(1000000)) 1091 1092 txs := types.Transactions{} 1093 for j := 0; j < int(config.GlobalSlots)*2; j++ { 1094 txs = append(txs, transaction(uint64(j), 100000, key)) 1095 } 1096 // Import the batch and verify that limits have been enforced 1097 pool.AddRemotes(txs) 1098 if err := validateTxPoolInternals(pool); err != nil { 1099 t.Fatalf("pool internal state corrupted: %v", err) 1100 } 1101 } 1102 1103 // Tests that if the transaction count belonging to multiple accounts go above 1104 // some hard threshold, if they are under the minimum guaranteed slot count then 1105 // the transactions are still kept. 1106 func TestTransactionPendingMinimumAllowance(t *testing.T) { 1107 t.Parallel() 1108 1109 // Create the pool to test the limit enforcement with 1110 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1111 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1112 1113 config := testTxPoolConfig 1114 config.GlobalSlots = 1 1115 1116 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1117 defer pool.Stop() 1118 1119 // Create a number of test accounts and fund them 1120 keys := make([]*ecdsa.PrivateKey, 5) 1121 for i := 0; i < len(keys); i++ { 1122 keys[i], _ = crypto.GenerateKey() 1123 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1124 } 1125 // Generate and queue a batch of transactions 1126 nonces := make(map[common.Address]uint64) 1127 1128 txs := types.Transactions{} 1129 for _, key := range keys { 1130 addr := crypto.PubkeyToAddress(key.PublicKey) 1131 for j := 0; j < int(config.AccountSlots)*2; j++ { 1132 txs = append(txs, transaction(nonces[addr], 100000, key)) 1133 nonces[addr]++ 1134 } 1135 } 1136 // Import the batch and verify that limits have been enforced 1137 pool.AddRemotesSync(txs) 1138 1139 for addr, list := range pool.pending { 1140 if list.Len() != int(config.AccountSlots) { 1141 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) 1142 } 1143 } 1144 if err := validateTxPoolInternals(pool); err != nil { 1145 t.Fatalf("pool internal state corrupted: %v", err) 1146 } 1147 } 1148 1149 // Tests that setting the transaction pool gas price to a higher value correctly 1150 // discards everything cheaper than that and moves any gapped transactions back 1151 // from the pending pool to the queue. 1152 // 1153 // Note, local transactions are never allowed to be dropped. 1154 func TestTransactionPoolRepricing(t *testing.T) { 1155 t.Parallel() 1156 1157 // Create the pool to test the pricing enforcement with 1158 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1159 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1160 1161 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1162 defer pool.Stop() 1163 1164 // Keep track of transaction events to ensure all executables get announced 1165 events := make(chan NewTxsEvent, 32) 1166 sub := pool.txFeed.Subscribe(events) 1167 defer sub.Unsubscribe() 1168 1169 // Create a number of test accounts and fund them 1170 keys := make([]*ecdsa.PrivateKey, 4) 1171 for i := 0; i < len(keys); i++ { 1172 keys[i], _ = crypto.GenerateKey() 1173 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1174 } 1175 // Generate and queue a batch of transactions, both pending and queued 1176 txs := types.Transactions{} 1177 1178 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) 1179 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) 1180 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) 1181 1182 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) 1183 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1])) 1184 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1])) 1185 1186 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2])) 1187 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) 1188 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2])) 1189 1190 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3]) 1191 1192 // Import the batch and that both pending and queued transactions match up 1193 pool.AddRemotesSync(txs) 1194 pool.AddLocal(ltx) 1195 1196 pending, queued := pool.Stats() 1197 if pending != 7 { 1198 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) 1199 } 1200 if queued != 3 { 1201 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1202 } 1203 if err := validateEvents(events, 7); err != nil { 1204 t.Fatalf("original event firing failed: %v", err) 1205 } 1206 if err := validateTxPoolInternals(pool); err != nil { 1207 t.Fatalf("pool internal state corrupted: %v", err) 1208 } 1209 // Reprice the pool and check that underpriced transactions get dropped 1210 pool.SetGasPrice(big.NewInt(2)) 1211 1212 pending, queued = pool.Stats() 1213 if pending != 2 { 1214 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1215 } 1216 if queued != 5 { 1217 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) 1218 } 1219 if err := validateEvents(events, 0); err != nil { 1220 t.Fatalf("reprice event firing failed: %v", err) 1221 } 1222 if err := validateTxPoolInternals(pool); err != nil { 1223 t.Fatalf("pool internal state corrupted: %v", err) 1224 } 1225 // Check that we can't add the old transactions back 1226 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced { 1227 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1228 } 1229 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1230 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1231 } 1232 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); err != ErrUnderpriced { 1233 t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1234 } 1235 if err := validateEvents(events, 0); err != nil { 1236 t.Fatalf("post-reprice event firing failed: %v", err) 1237 } 1238 if err := validateTxPoolInternals(pool); err != nil { 1239 t.Fatalf("pool internal state corrupted: %v", err) 1240 } 1241 // However we can add local underpriced transactions 1242 tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3]) 1243 if err := pool.AddLocal(tx); err != nil { 1244 t.Fatalf("failed to add underpriced local transaction: %v", err) 1245 } 1246 if pending, _ = pool.Stats(); pending != 3 { 1247 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1248 } 1249 if err := validateEvents(events, 1); err != nil { 1250 t.Fatalf("post-reprice local event firing failed: %v", err) 1251 } 1252 if err := validateTxPoolInternals(pool); err != nil { 1253 t.Fatalf("pool internal state corrupted: %v", err) 1254 } 1255 // And we can fill gaps with properly priced transactions 1256 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil { 1257 t.Fatalf("failed to add pending transaction: %v", err) 1258 } 1259 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil { 1260 t.Fatalf("failed to add pending transaction: %v", err) 1261 } 1262 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil { 1263 t.Fatalf("failed to add queued transaction: %v", err) 1264 } 1265 if err := validateEvents(events, 5); err != nil { 1266 t.Fatalf("post-reprice event firing failed: %v", err) 1267 } 1268 if err := validateTxPoolInternals(pool); err != nil { 1269 t.Fatalf("pool internal state corrupted: %v", err) 1270 } 1271 } 1272 1273 // Tests that setting the transaction pool gas price to a higher value does not 1274 // remove local transactions. 1275 func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { 1276 t.Parallel() 1277 1278 // Create the pool to test the pricing enforcement with 1279 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1280 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1281 1282 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1283 defer pool.Stop() 1284 1285 // Create a number of test accounts and fund them 1286 keys := make([]*ecdsa.PrivateKey, 3) 1287 for i := 0; i < len(keys); i++ { 1288 keys[i], _ = crypto.GenerateKey() 1289 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) 1290 } 1291 // Create transaction (both pending and queued) with a linearly growing gasprice 1292 for i := uint64(0); i < 500; i++ { 1293 // Add pending transaction. 1294 pendingTx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2]) 1295 if err := pool.AddLocal(pendingTx); err != nil { 1296 t.Fatal(err) 1297 } 1298 // Add queued transaction. 1299 queuedTx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2]) 1300 if err := pool.AddLocal(queuedTx); err != nil { 1301 t.Fatal(err) 1302 } 1303 } 1304 pending, queued := pool.Stats() 1305 expPending, expQueued := 500, 500 1306 validate := func() { 1307 pending, queued = pool.Stats() 1308 if pending != expPending { 1309 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) 1310 } 1311 if queued != expQueued { 1312 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) 1313 } 1314 1315 if err := validateTxPoolInternals(pool); err != nil { 1316 t.Fatalf("pool internal state corrupted: %v", err) 1317 } 1318 } 1319 validate() 1320 1321 // Reprice the pool and check that nothing is dropped 1322 pool.SetGasPrice(big.NewInt(2)) 1323 validate() 1324 1325 pool.SetGasPrice(big.NewInt(2)) 1326 pool.SetGasPrice(big.NewInt(4)) 1327 pool.SetGasPrice(big.NewInt(8)) 1328 pool.SetGasPrice(big.NewInt(100)) 1329 validate() 1330 } 1331 1332 // Tests that when the pool reaches its global transaction limit, underpriced 1333 // transactions are gradually shifted out for more expensive ones and any gapped 1334 // pending transactions are moved into the queue. 1335 // 1336 // Note, local transactions are never allowed to be dropped. 1337 func TestTransactionPoolUnderpricing(t *testing.T) { 1338 t.Parallel() 1339 1340 // Create the pool to test the pricing enforcement with 1341 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1342 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1343 1344 config := testTxPoolConfig 1345 config.GlobalSlots = 2 1346 config.GlobalQueue = 2 1347 1348 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1349 defer pool.Stop() 1350 1351 // Keep track of transaction events to ensure all executables get announced 1352 events := make(chan NewTxsEvent, 32) 1353 sub := pool.txFeed.Subscribe(events) 1354 defer sub.Unsubscribe() 1355 1356 // Create a number of test accounts and fund them 1357 keys := make([]*ecdsa.PrivateKey, 4) 1358 for i := 0; i < len(keys); i++ { 1359 keys[i], _ = crypto.GenerateKey() 1360 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1361 } 1362 // Generate and queue a batch of transactions, both pending and queued 1363 txs := types.Transactions{} 1364 1365 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) 1366 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) 1367 1368 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) 1369 1370 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) 1371 1372 // Import the batch and that both pending and queued transactions match up 1373 pool.AddRemotes(txs) 1374 pool.AddLocal(ltx) 1375 1376 pending, queued := pool.Stats() 1377 if pending != 3 { 1378 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1379 } 1380 if queued != 1 { 1381 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1382 } 1383 if err := validateEvents(events, 3); err != nil { 1384 t.Fatalf("original event firing failed: %v", err) 1385 } 1386 if err := validateTxPoolInternals(pool); err != nil { 1387 t.Fatalf("pool internal state corrupted: %v", err) 1388 } 1389 // Ensure that adding an underpriced transaction on block limit fails 1390 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1391 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1392 } 1393 // Ensure that adding high priced transactions drops cheap ones, but not own 1394 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 - 1395 t.Fatalf("failed to add well priced transaction: %v", err) 1396 } 1397 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 1398 t.Fatalf("failed to add well priced transaction: %v", err) 1399 } 1400 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 1401 t.Fatalf("failed to add well priced transaction: %v", err) 1402 } 1403 pending, queued = pool.Stats() 1404 if pending != 2 { 1405 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1406 } 1407 if queued != 2 { 1408 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1409 } 1410 if err := validateEvents(events, 1); err != nil { 1411 t.Fatalf("additional event firing failed: %v", err) 1412 } 1413 if err := validateTxPoolInternals(pool); err != nil { 1414 t.Fatalf("pool internal state corrupted: %v", err) 1415 } 1416 // Ensure that adding local transactions can push out even higher priced ones 1417 ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2]) 1418 if err := pool.AddLocal(ltx); err != nil { 1419 t.Fatalf("failed to append underpriced local transaction: %v", err) 1420 } 1421 ltx = pricedTransaction(0, 100000, big.NewInt(0), keys[3]) 1422 if err := pool.AddLocal(ltx); err != nil { 1423 t.Fatalf("failed to add new underpriced local transaction: %v", err) 1424 } 1425 pending, queued = pool.Stats() 1426 if pending != 3 { 1427 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1428 } 1429 if queued != 1 { 1430 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1431 } 1432 if err := validateEvents(events, 2); err != nil { 1433 t.Fatalf("local event firing failed: %v", err) 1434 } 1435 if err := validateTxPoolInternals(pool); err != nil { 1436 t.Fatalf("pool internal state corrupted: %v", err) 1437 } 1438 } 1439 1440 // Tests that more expensive transactions push out cheap ones from the pool, but 1441 // without producing instability by creating gaps that start jumping transactions 1442 // back and forth between queued/pending. 1443 func TestTransactionPoolStableUnderpricing(t *testing.T) { 1444 t.Parallel() 1445 1446 // Create the pool to test the pricing enforcement with 1447 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1448 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1449 1450 config := testTxPoolConfig 1451 config.GlobalSlots = 128 1452 config.GlobalQueue = 0 1453 1454 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1455 defer pool.Stop() 1456 1457 // Keep track of transaction events to ensure all executables get announced 1458 events := make(chan NewTxsEvent, 32) 1459 sub := pool.txFeed.Subscribe(events) 1460 defer sub.Unsubscribe() 1461 1462 // Create a number of test accounts and fund them 1463 keys := make([]*ecdsa.PrivateKey, 2) 1464 for i := 0; i < len(keys); i++ { 1465 keys[i], _ = crypto.GenerateKey() 1466 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1467 } 1468 // Fill up the entire queue with the same transaction price points 1469 txs := types.Transactions{} 1470 for i := uint64(0); i < config.GlobalSlots; i++ { 1471 txs = append(txs, pricedTransaction(i, 100000, big.NewInt(1), keys[0])) 1472 } 1473 pool.AddRemotesSync(txs) 1474 1475 pending, queued := pool.Stats() 1476 if pending != int(config.GlobalSlots) { 1477 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots) 1478 } 1479 if queued != 0 { 1480 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1481 } 1482 if err := validateEvents(events, int(config.GlobalSlots)); err != nil { 1483 t.Fatalf("original event firing failed: %v", err) 1484 } 1485 if err := validateTxPoolInternals(pool); err != nil { 1486 t.Fatalf("pool internal state corrupted: %v", err) 1487 } 1488 // Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap 1489 if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { 1490 t.Fatalf("failed to add well priced transaction: %v", err) 1491 } 1492 pending, queued = pool.Stats() 1493 if pending != int(config.GlobalSlots) { 1494 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, config.GlobalSlots) 1495 } 1496 if queued != 0 { 1497 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1498 } 1499 if err := validateEvents(events, 1); err != nil { 1500 t.Fatalf("additional event firing failed: %v", err) 1501 } 1502 if err := validateTxPoolInternals(pool); err != nil { 1503 t.Fatalf("pool internal state corrupted: %v", err) 1504 } 1505 } 1506 1507 // Tests that the pool rejects duplicate transactions. 1508 func TestTransactionDeduplication(t *testing.T) { 1509 t.Parallel() 1510 1511 // Create the pool to test the pricing enforcement with 1512 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1513 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1514 1515 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1516 defer pool.Stop() 1517 1518 // Create a test account to add transactions with 1519 key, _ := crypto.GenerateKey() 1520 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1521 1522 // Create a batch of transactions and add a few of them 1523 txs := make([]*types.Transaction, 16) 1524 for i := 0; i < len(txs); i++ { 1525 txs[i] = pricedTransaction(uint64(i), 100000, big.NewInt(1), key) 1526 } 1527 var firsts []*types.Transaction 1528 for i := 0; i < len(txs); i += 2 { 1529 firsts = append(firsts, txs[i]) 1530 } 1531 errs := pool.AddRemotesSync(firsts) 1532 if len(errs) != len(firsts) { 1533 t.Fatalf("first add mismatching result count: have %d, want %d", len(errs), len(firsts)) 1534 } 1535 for i, err := range errs { 1536 if err != nil { 1537 t.Errorf("add %d failed: %v", i, err) 1538 } 1539 } 1540 pending, queued := pool.Stats() 1541 if pending != 1 { 1542 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) 1543 } 1544 if queued != len(txs)/2-1 { 1545 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, len(txs)/2-1) 1546 } 1547 // Try to add all of them now and ensure previous ones error out as knowns 1548 errs = pool.AddRemotesSync(txs) 1549 if len(errs) != len(txs) { 1550 t.Fatalf("all add mismatching result count: have %d, want %d", len(errs), len(txs)) 1551 } 1552 for i, err := range errs { 1553 if i%2 == 0 && err == nil { 1554 t.Errorf("add %d succeeded, should have failed as known", i) 1555 } 1556 if i%2 == 1 && err != nil { 1557 t.Errorf("add %d failed: %v", i, err) 1558 } 1559 } 1560 pending, queued = pool.Stats() 1561 if pending != len(txs) { 1562 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, len(txs)) 1563 } 1564 if queued != 0 { 1565 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1566 } 1567 if err := validateTxPoolInternals(pool); err != nil { 1568 t.Fatalf("pool internal state corrupted: %v", err) 1569 } 1570 } 1571 1572 // Tests that the pool rejects replacement transactions that don't meet the minimum 1573 // price bump required. 1574 func TestTransactionReplacement(t *testing.T) { 1575 t.Parallel() 1576 1577 // Create the pool to test the pricing enforcement with 1578 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1579 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1580 1581 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1582 defer pool.Stop() 1583 1584 // Keep track of transaction events to ensure all executables get announced 1585 events := make(chan NewTxsEvent, 32) 1586 sub := pool.txFeed.Subscribe(events) 1587 defer sub.Unsubscribe() 1588 1589 // Create a test account to add transactions with 1590 key, _ := crypto.GenerateKey() 1591 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1592 1593 // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1594 price := int64(100) 1595 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 1596 1597 if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { 1598 t.Fatalf("failed to add original cheap pending transaction: %v", err) 1599 } 1600 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1601 t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1602 } 1603 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { 1604 t.Fatalf("failed to replace original cheap pending transaction: %v", err) 1605 } 1606 if err := validateEvents(events, 2); err != nil { 1607 t.Fatalf("cheap replacement event firing failed: %v", err) 1608 } 1609 1610 if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { 1611 t.Fatalf("failed to add original proper pending transaction: %v", err) 1612 } 1613 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1614 t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1615 } 1616 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { 1617 t.Fatalf("failed to replace original proper pending transaction: %v", err) 1618 } 1619 if err := validateEvents(events, 2); err != nil { 1620 t.Fatalf("proper replacement event firing failed: %v", err) 1621 } 1622 1623 // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1624 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { 1625 t.Fatalf("failed to add original cheap queued transaction: %v", err) 1626 } 1627 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1628 t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1629 } 1630 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { 1631 t.Fatalf("failed to replace original cheap queued transaction: %v", err) 1632 } 1633 1634 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { 1635 t.Fatalf("failed to add original proper queued transaction: %v", err) 1636 } 1637 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1638 t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1639 } 1640 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { 1641 t.Fatalf("failed to replace original proper queued transaction: %v", err) 1642 } 1643 1644 if err := validateEvents(events, 0); err != nil { 1645 t.Fatalf("queued replacement event firing failed: %v", err) 1646 } 1647 if err := validateTxPoolInternals(pool); err != nil { 1648 t.Fatalf("pool internal state corrupted: %v", err) 1649 } 1650 } 1651 1652 // Tests that local transactions are journaled to disk, but remote transactions 1653 // get discarded between restarts. 1654 func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } 1655 func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } 1656 1657 func testTransactionJournaling(t *testing.T, nolocals bool) { 1658 t.Parallel() 1659 1660 // Create a temporary file for the journal 1661 file, err := ioutil.TempFile("", "") 1662 if err != nil { 1663 t.Fatalf("failed to create temporary journal: %v", err) 1664 } 1665 journal := file.Name() 1666 defer os.Remove(journal) 1667 1668 // Clean up the temporary file, we only need the path for now 1669 file.Close() 1670 os.Remove(journal) 1671 1672 // Create the original pool to inject transaction into the journal 1673 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1674 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1675 1676 config := testTxPoolConfig 1677 config.NoLocals = nolocals 1678 config.Journal = journal 1679 config.Rejournal = time.Second 1680 1681 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1682 1683 // Create two test accounts to ensure remotes expire but locals do not 1684 local, _ := crypto.GenerateKey() 1685 remote, _ := crypto.GenerateKey() 1686 1687 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1688 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1689 1690 // Add three local and a remote transactions and ensure they are queued up 1691 if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil { 1692 t.Fatalf("failed to add local transaction: %v", err) 1693 } 1694 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 1695 t.Fatalf("failed to add local transaction: %v", err) 1696 } 1697 if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { 1698 t.Fatalf("failed to add local transaction: %v", err) 1699 } 1700 if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil { 1701 t.Fatalf("failed to add remote transaction: %v", err) 1702 } 1703 pending, queued := pool.Stats() 1704 if pending != 4 { 1705 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1706 } 1707 if queued != 0 { 1708 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1709 } 1710 if err := validateTxPoolInternals(pool); err != nil { 1711 t.Fatalf("pool internal state corrupted: %v", err) 1712 } 1713 // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive 1714 pool.Stop() 1715 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1716 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1717 1718 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1719 1720 pending, queued = pool.Stats() 1721 if queued != 0 { 1722 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1723 } 1724 if nolocals { 1725 if pending != 0 { 1726 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1727 } 1728 } else { 1729 if pending != 2 { 1730 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1731 } 1732 } 1733 if err := validateTxPoolInternals(pool); err != nil { 1734 t.Fatalf("pool internal state corrupted: %v", err) 1735 } 1736 // Bump the nonce temporarily and ensure the newly invalidated transaction is removed 1737 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) 1738 <-pool.requestReset(nil, nil) 1739 time.Sleep(2 * config.Rejournal) 1740 pool.Stop() 1741 1742 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1743 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1744 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1745 1746 pending, queued = pool.Stats() 1747 if pending != 0 { 1748 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1749 } 1750 if nolocals { 1751 if queued != 0 { 1752 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1753 } 1754 } else { 1755 if queued != 1 { 1756 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1757 } 1758 } 1759 if err := validateTxPoolInternals(pool); err != nil { 1760 t.Fatalf("pool internal state corrupted: %v", err) 1761 } 1762 pool.Stop() 1763 } 1764 1765 // TestTransactionStatusCheck tests that the pool can correctly retrieve the 1766 // pending status of individual transactions. 1767 func TestTransactionStatusCheck(t *testing.T) { 1768 t.Parallel() 1769 1770 // Create the pool to test the status retrievals with 1771 statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase())) 1772 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1773 1774 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1775 defer pool.Stop() 1776 1777 // Create the test accounts to check various transaction statuses with 1778 keys := make([]*ecdsa.PrivateKey, 3) 1779 for i := 0; i < len(keys); i++ { 1780 keys[i], _ = crypto.GenerateKey() 1781 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1782 } 1783 // Generate and queue a batch of transactions, both pending and queued 1784 txs := types.Transactions{} 1785 1786 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // Pending only 1787 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) // Pending and queued 1788 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) 1789 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) // Queued only 1790 1791 // Import the transaction and ensure they are correctly added 1792 pool.AddRemotesSync(txs) 1793 1794 pending, queued := pool.Stats() 1795 if pending != 2 { 1796 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1797 } 1798 if queued != 2 { 1799 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1800 } 1801 if err := validateTxPoolInternals(pool); err != nil { 1802 t.Fatalf("pool internal state corrupted: %v", err) 1803 } 1804 // Retrieve the status of each transaction and validate them 1805 hashes := make([]common.Hash, len(txs)) 1806 for i, tx := range txs { 1807 hashes[i] = tx.Hash() 1808 } 1809 hashes = append(hashes, common.Hash{}) 1810 1811 statuses := pool.Status(hashes) 1812 expect := []TxStatus{TxStatusPending, TxStatusPending, TxStatusQueued, TxStatusQueued, TxStatusUnknown} 1813 1814 for i := 0; i < len(statuses); i++ { 1815 if statuses[i] != expect[i] { 1816 t.Errorf("transaction %d: status mismatch: have %v, want %v", i, statuses[i], expect[i]) 1817 } 1818 } 1819 } 1820 1821 // Test the transaction slots consumption is computed correctly 1822 func TestTransactionSlotCount(t *testing.T) { 1823 t.Parallel() 1824 1825 key, _ := crypto.GenerateKey() 1826 1827 // Check that an empty transaction consumes a single slot 1828 smallTx := pricedDataTransaction(0, 0, big.NewInt(0), key, 0) 1829 if slots := numSlots(smallTx); slots != 1 { 1830 t.Fatalf("small transactions slot count mismatch: have %d want %d", slots, 1) 1831 } 1832 // Check that a large transaction consumes the correct number of slots 1833 bigTx := pricedDataTransaction(0, 0, big.NewInt(0), key, uint64(10*txSlotSize)) 1834 if slots := numSlots(bigTx); slots != 11 { 1835 t.Fatalf("big transactions slot count mismatch: have %d want %d", slots, 11) 1836 } 1837 } 1838 1839 // Benchmarks the speed of validating the contents of the pending queue of the 1840 // transaction pool. 1841 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 1842 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 1843 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 1844 1845 func benchmarkPendingDemotion(b *testing.B, size int) { 1846 // Add a batch of transactions to a pool one by one 1847 pool, key := setupTxPool() 1848 defer pool.Stop() 1849 1850 account := crypto.PubkeyToAddress(key.PublicKey) 1851 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1852 1853 for i := 0; i < size; i++ { 1854 tx := transaction(uint64(i), 100000, key) 1855 pool.promoteTx(account, tx.Hash(), tx) 1856 } 1857 // Benchmark the speed of pool validation 1858 b.ResetTimer() 1859 for i := 0; i < b.N; i++ { 1860 pool.demoteUnexecutables() 1861 } 1862 } 1863 1864 // Benchmarks the speed of scheduling the contents of the future queue of the 1865 // transaction pool. 1866 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 1867 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 1868 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 1869 1870 func benchmarkFuturePromotion(b *testing.B, size int) { 1871 // Add a batch of transactions to a pool one by one 1872 pool, key := setupTxPool() 1873 defer pool.Stop() 1874 1875 account := crypto.PubkeyToAddress(key.PublicKey) 1876 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1877 1878 for i := 0; i < size; i++ { 1879 tx := transaction(uint64(1+i), 100000, key) 1880 pool.enqueueTx(tx.Hash(), tx) 1881 } 1882 // Benchmark the speed of pool validation 1883 b.ResetTimer() 1884 for i := 0; i < b.N; i++ { 1885 pool.promoteExecutables(nil) 1886 } 1887 } 1888 1889 // Benchmarks the speed of batched transaction insertion. 1890 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 1891 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 1892 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 1893 1894 func benchmarkPoolBatchInsert(b *testing.B, size int) { 1895 // Generate a batch of transactions to enqueue into the pool 1896 pool, key := setupTxPool() 1897 defer pool.Stop() 1898 1899 account := crypto.PubkeyToAddress(key.PublicKey) 1900 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1901 1902 batches := make([]types.Transactions, b.N) 1903 for i := 0; i < b.N; i++ { 1904 batches[i] = make(types.Transactions, size) 1905 for j := 0; j < size; j++ { 1906 batches[i][j] = transaction(uint64(size*i+j), 100000, key) 1907 } 1908 } 1909 // Benchmark importing the transactions into the queue 1910 b.ResetTimer() 1911 for _, batch := range batches { 1912 pool.AddRemotes(batch) 1913 } 1914 }