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