github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/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 "math/big" 22 "math/rand" 23 "testing" 24 "time" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/core/state" 28 "github.com/ethereum/go-ethereum/core/types" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/ethdb" 31 "github.com/ethereum/go-ethereum/event" 32 "github.com/ethereum/go-ethereum/params" 33 ) 34 35 func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 36 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil), types.HomesteadSigner{}, key) 37 return tx 38 } 39 40 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 41 db, _ := ethdb.NewMemDatabase() 42 statedb, _ := state.New(common.Hash{}, db) 43 44 key, _ := crypto.GenerateKey() 45 newPool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) 46 newPool.resetState() 47 48 return newPool, key 49 } 50 51 func deriveSender(tx *types.Transaction) (common.Address, error) { 52 return types.Sender(types.HomesteadSigner{}, tx) 53 } 54 55 // This test simulates a scenario where a new block is imported during a 56 // state reset and tests whether the pending state is in sync with the 57 // block head event that initiated the resetState(). 58 func TestStateChangeDuringPoolReset(t *testing.T) { 59 var ( 60 db, _ = ethdb.NewMemDatabase() 61 key, _ = crypto.GenerateKey() 62 address = crypto.PubkeyToAddress(key.PublicKey) 63 mux = new(event.TypeMux) 64 statedb, _ = state.New(common.Hash{}, db) 65 trigger = false 66 ) 67 68 // setup pool with 2 transaction in it 69 statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) 70 71 tx0 := transaction(0, big.NewInt(100000), key) 72 tx1 := transaction(1, big.NewInt(100000), key) 73 74 // stateFunc is used multiple times to reset the pending state. 75 // when simulate is true it will create a state that indicates 76 // that tx0 and tx1 are included in the chain. 77 stateFunc := func() (*state.StateDB, error) { 78 // delay "state change" by one. The tx pool fetches the 79 // state multiple times and by delaying it a bit we simulate 80 // a state change between those fetches. 81 stdb := statedb 82 if trigger { 83 statedb, _ = state.New(common.Hash{}, db) 84 // simulate that the new head block included tx0 and tx1 85 statedb.SetNonce(address, 2) 86 statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) 87 trigger = false 88 } 89 return stdb, nil 90 } 91 92 gasLimitFunc := func() *big.Int { return big.NewInt(1000000000) } 93 94 txpool := NewTxPool(params.TestChainConfig, mux, stateFunc, gasLimitFunc) 95 txpool.resetState() 96 97 nonce := txpool.State().GetNonce(address) 98 if nonce != 0 { 99 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 100 } 101 102 txpool.AddBatch(types.Transactions{tx0, tx1}) 103 104 nonce = txpool.State().GetNonce(address) 105 if nonce != 2 { 106 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 107 } 108 109 // trigger state change in the background 110 trigger = true 111 112 txpool.resetState() 113 114 pendingTx, err := txpool.Pending() 115 if err != nil { 116 t.Fatalf("Could not fetch pending transactions: %v", err) 117 } 118 119 for addr, txs := range pendingTx { 120 t.Logf("%0x: %d\n", addr, len(txs)) 121 } 122 123 nonce = txpool.State().GetNonce(address) 124 if nonce != 2 { 125 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 126 } 127 } 128 129 func TestInvalidTransactions(t *testing.T) { 130 pool, key := setupTxPool() 131 132 tx := transaction(0, big.NewInt(100), key) 133 from, _ := deriveSender(tx) 134 currentState, _ := pool.currentState() 135 currentState.AddBalance(from, big.NewInt(1)) 136 if err := pool.Add(tx); err != ErrInsufficientFunds { 137 t.Error("expected", ErrInsufficientFunds) 138 } 139 140 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice())) 141 currentState.AddBalance(from, balance) 142 if err := pool.Add(tx); err != ErrIntrinsicGas { 143 t.Error("expected", ErrIntrinsicGas, "got", err) 144 } 145 146 currentState.SetNonce(from, 1) 147 currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) 148 tx = transaction(0, big.NewInt(100000), key) 149 if err := pool.Add(tx); err != ErrNonce { 150 t.Error("expected", ErrNonce) 151 } 152 153 tx = transaction(1, big.NewInt(100000), key) 154 pool.minGasPrice = big.NewInt(1000) 155 if err := pool.Add(tx); err != ErrCheap { 156 t.Error("expected", ErrCheap, "got", err) 157 } 158 159 pool.SetLocal(tx) 160 if err := pool.Add(tx); err != nil { 161 t.Error("expected", nil, "got", err) 162 } 163 } 164 165 func TestTransactionQueue(t *testing.T) { 166 pool, key := setupTxPool() 167 tx := transaction(0, big.NewInt(100), key) 168 from, _ := deriveSender(tx) 169 currentState, _ := pool.currentState() 170 currentState.AddBalance(from, big.NewInt(1000)) 171 pool.resetState() 172 pool.enqueueTx(tx.Hash(), tx) 173 174 pool.promoteExecutables(currentState) 175 if len(pool.pending) != 1 { 176 t.Error("expected valid txs to be 1 is", len(pool.pending)) 177 } 178 179 tx = transaction(1, big.NewInt(100), key) 180 from, _ = deriveSender(tx) 181 currentState.SetNonce(from, 2) 182 pool.enqueueTx(tx.Hash(), tx) 183 pool.promoteExecutables(currentState) 184 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 185 t.Error("expected transaction to be in tx pool") 186 } 187 188 if len(pool.queue) > 0 { 189 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 190 } 191 192 pool, key = setupTxPool() 193 tx1 := transaction(0, big.NewInt(100), key) 194 tx2 := transaction(10, big.NewInt(100), key) 195 tx3 := transaction(11, big.NewInt(100), key) 196 from, _ = deriveSender(tx1) 197 currentState, _ = pool.currentState() 198 currentState.AddBalance(from, big.NewInt(1000)) 199 pool.resetState() 200 201 pool.enqueueTx(tx1.Hash(), tx1) 202 pool.enqueueTx(tx2.Hash(), tx2) 203 pool.enqueueTx(tx3.Hash(), tx3) 204 205 pool.promoteExecutables(currentState) 206 207 if len(pool.pending) != 1 { 208 t.Error("expected tx pool to be 1, got", len(pool.pending)) 209 } 210 if pool.queue[from].Len() != 2 { 211 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 212 } 213 } 214 215 func TestRemoveTx(t *testing.T) { 216 pool, key := setupTxPool() 217 tx := transaction(0, big.NewInt(100), key) 218 from, _ := deriveSender(tx) 219 currentState, _ := pool.currentState() 220 currentState.AddBalance(from, big.NewInt(1)) 221 222 pool.enqueueTx(tx.Hash(), tx) 223 pool.promoteTx(from, tx.Hash(), tx) 224 if len(pool.queue) != 1 { 225 t.Error("expected queue to be 1, got", len(pool.queue)) 226 } 227 if len(pool.pending) != 1 { 228 t.Error("expected pending to be 1, got", len(pool.pending)) 229 } 230 pool.Remove(tx.Hash()) 231 if len(pool.queue) > 0 { 232 t.Error("expected queue to be 0, got", len(pool.queue)) 233 } 234 if len(pool.pending) > 0 { 235 t.Error("expected pending to be 0, got", len(pool.pending)) 236 } 237 } 238 239 func TestNegativeValue(t *testing.T) { 240 pool, key := setupTxPool() 241 242 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key) 243 from, _ := deriveSender(tx) 244 currentState, _ := pool.currentState() 245 currentState.AddBalance(from, big.NewInt(1)) 246 if err := pool.Add(tx); err != ErrNegativeValue { 247 t.Error("expected", ErrNegativeValue, "got", err) 248 } 249 } 250 251 func TestTransactionChainFork(t *testing.T) { 252 pool, key := setupTxPool() 253 addr := crypto.PubkeyToAddress(key.PublicKey) 254 resetState := func() { 255 db, _ := ethdb.NewMemDatabase() 256 statedb, _ := state.New(common.Hash{}, db) 257 pool.currentState = func() (*state.StateDB, error) { return statedb, nil } 258 currentState, _ := pool.currentState() 259 currentState.AddBalance(addr, big.NewInt(100000000000000)) 260 pool.resetState() 261 } 262 resetState() 263 264 tx := transaction(0, big.NewInt(100000), key) 265 if err := pool.add(tx); err != nil { 266 t.Error("didn't expect error", err) 267 } 268 pool.RemoveBatch([]*types.Transaction{tx}) 269 270 // reset the pool's internal state 271 resetState() 272 if err := pool.add(tx); err != nil { 273 t.Error("didn't expect error", err) 274 } 275 } 276 277 func TestTransactionDoubleNonce(t *testing.T) { 278 pool, key := setupTxPool() 279 addr := crypto.PubkeyToAddress(key.PublicKey) 280 resetState := func() { 281 db, _ := ethdb.NewMemDatabase() 282 statedb, _ := state.New(common.Hash{}, db) 283 pool.currentState = func() (*state.StateDB, error) { return statedb, nil } 284 currentState, _ := pool.currentState() 285 currentState.AddBalance(addr, big.NewInt(100000000000000)) 286 pool.resetState() 287 } 288 resetState() 289 290 signer := types.HomesteadSigner{} 291 tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key) 292 tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key) 293 tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key) 294 295 // Add the first two transaction, ensure higher priced stays only 296 if err := pool.add(tx1); err != nil { 297 t.Error("didn't expect error", err) 298 } 299 if err := pool.add(tx2); err != nil { 300 t.Error("didn't expect error", err) 301 } 302 state, _ := pool.currentState() 303 pool.promoteExecutables(state) 304 if pool.pending[addr].Len() != 1 { 305 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 306 } 307 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 308 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 309 } 310 // Add the thid transaction and ensure it's not saved (smaller price) 311 if err := pool.add(tx3); err != nil { 312 t.Error("didn't expect error", err) 313 } 314 pool.promoteExecutables(state) 315 if pool.pending[addr].Len() != 1 { 316 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 317 } 318 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 319 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 320 } 321 // Ensure the total transaction count is correct 322 if len(pool.all) != 1 { 323 t.Error("expected 1 total transactions, got", len(pool.all)) 324 } 325 } 326 327 func TestMissingNonce(t *testing.T) { 328 pool, key := setupTxPool() 329 addr := crypto.PubkeyToAddress(key.PublicKey) 330 currentState, _ := pool.currentState() 331 currentState.AddBalance(addr, big.NewInt(100000000000000)) 332 tx := transaction(1, big.NewInt(100000), key) 333 if err := pool.add(tx); err != nil { 334 t.Error("didn't expect error", err) 335 } 336 if len(pool.pending) != 0 { 337 t.Error("expected 0 pending transactions, got", len(pool.pending)) 338 } 339 if pool.queue[addr].Len() != 1 { 340 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 341 } 342 if len(pool.all) != 1 { 343 t.Error("expected 1 total transactions, got", len(pool.all)) 344 } 345 } 346 347 func TestNonceRecovery(t *testing.T) { 348 const n = 10 349 pool, key := setupTxPool() 350 addr := crypto.PubkeyToAddress(key.PublicKey) 351 currentState, _ := pool.currentState() 352 currentState.SetNonce(addr, n) 353 currentState.AddBalance(addr, big.NewInt(100000000000000)) 354 pool.resetState() 355 tx := transaction(n, big.NewInt(100000), key) 356 if err := pool.Add(tx); err != nil { 357 t.Error(err) 358 } 359 // simulate some weird re-order of transactions and missing nonce(s) 360 currentState.SetNonce(addr, n-1) 361 pool.resetState() 362 if fn := pool.pendingState.GetNonce(addr); fn != n+1 { 363 t.Errorf("expected nonce to be %d, got %d", n+1, fn) 364 } 365 } 366 367 func TestRemovedTxEvent(t *testing.T) { 368 pool, key := setupTxPool() 369 tx := transaction(0, big.NewInt(1000000), key) 370 from, _ := deriveSender(tx) 371 currentState, _ := pool.currentState() 372 currentState.AddBalance(from, big.NewInt(1000000000000)) 373 pool.resetState() 374 pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}}) 375 pool.eventMux.Post(ChainHeadEvent{nil}) 376 if pool.pending[from].Len() != 1 { 377 t.Error("expected 1 pending tx, got", pool.pending[from].Len()) 378 } 379 if len(pool.all) != 1 { 380 t.Error("expected 1 total transactions, got", len(pool.all)) 381 } 382 } 383 384 // Tests that if an account runs out of funds, any pending and queued transactions 385 // are dropped. 386 func TestTransactionDropping(t *testing.T) { 387 // Create a test account and fund it 388 pool, key := setupTxPool() 389 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 390 391 state, _ := pool.currentState() 392 state.AddBalance(account, big.NewInt(1000)) 393 394 // Add some pending and some queued transactions 395 var ( 396 tx0 = transaction(0, big.NewInt(100), key) 397 tx1 = transaction(1, big.NewInt(200), key) 398 tx10 = transaction(10, big.NewInt(100), key) 399 tx11 = transaction(11, big.NewInt(200), key) 400 ) 401 pool.promoteTx(account, tx0.Hash(), tx0) 402 pool.promoteTx(account, tx1.Hash(), tx1) 403 pool.enqueueTx(tx10.Hash(), tx10) 404 pool.enqueueTx(tx11.Hash(), tx11) 405 406 // Check that pre and post validations leave the pool as is 407 if pool.pending[account].Len() != 2 { 408 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 2) 409 } 410 if pool.queue[account].Len() != 2 { 411 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 2) 412 } 413 if len(pool.all) != 4 { 414 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) 415 } 416 pool.resetState() 417 if pool.pending[account].Len() != 2 { 418 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 2) 419 } 420 if pool.queue[account].Len() != 2 { 421 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 2) 422 } 423 if len(pool.all) != 4 { 424 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) 425 } 426 // Reduce the balance of the account, and check that invalidated transactions are dropped 427 state.AddBalance(account, big.NewInt(-750)) 428 pool.resetState() 429 430 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 431 t.Errorf("funded pending transaction missing: %v", tx0) 432 } 433 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { 434 t.Errorf("out-of-fund pending transaction present: %v", tx1) 435 } 436 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 437 t.Errorf("funded queued transaction missing: %v", tx10) 438 } 439 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { 440 t.Errorf("out-of-fund queued transaction present: %v", tx11) 441 } 442 if len(pool.all) != 2 { 443 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2) 444 } 445 } 446 447 // Tests that if a transaction is dropped from the current pending pool (e.g. out 448 // of fund), all consecutive (still valid, but not executable) transactions are 449 // postponed back into the future queue to prevent broadcasting them. 450 func TestTransactionPostponing(t *testing.T) { 451 // Create a test account and fund it 452 pool, key := setupTxPool() 453 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 454 455 state, _ := pool.currentState() 456 state.AddBalance(account, big.NewInt(1000)) 457 458 // Add a batch consecutive pending transactions for validation 459 txns := []*types.Transaction{} 460 for i := 0; i < 100; i++ { 461 var tx *types.Transaction 462 if i%2 == 0 { 463 tx = transaction(uint64(i), big.NewInt(100), key) 464 } else { 465 tx = transaction(uint64(i), big.NewInt(500), key) 466 } 467 pool.promoteTx(account, tx.Hash(), tx) 468 txns = append(txns, tx) 469 } 470 // Check that pre and post validations leave the pool as is 471 if pool.pending[account].Len() != len(txns) { 472 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns)) 473 } 474 if len(pool.queue) != 0 { 475 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0) 476 } 477 if len(pool.all) != len(txns) { 478 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)) 479 } 480 pool.resetState() 481 if pool.pending[account].Len() != len(txns) { 482 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns)) 483 } 484 if len(pool.queue) != 0 { 485 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0) 486 } 487 if len(pool.all) != len(txns) { 488 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)) 489 } 490 // Reduce the balance of the account, and check that transactions are reorganised 491 state.AddBalance(account, big.NewInt(-750)) 492 pool.resetState() 493 494 if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok { 495 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0]) 496 } 497 if _, ok := pool.queue[account].txs.items[txns[0].Nonce()]; ok { 498 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0]) 499 } 500 for i, tx := range txns[1:] { 501 if i%2 == 1 { 502 if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok { 503 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 504 } 505 if _, ok := pool.queue[account].txs.items[tx.Nonce()]; !ok { 506 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 507 } 508 } else { 509 if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok { 510 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 511 } 512 if _, ok := pool.queue[account].txs.items[tx.Nonce()]; ok { 513 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 514 } 515 } 516 } 517 if len(pool.all) != len(txns)/2 { 518 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)/2) 519 } 520 } 521 522 // Tests that if the transaction count belonging to a single account goes above 523 // some threshold, the higher transactions are dropped to prevent DOS attacks. 524 func TestTransactionQueueAccountLimiting(t *testing.T) { 525 // Create a test account and fund it 526 pool, key := setupTxPool() 527 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 528 529 state, _ := pool.currentState() 530 state.AddBalance(account, big.NewInt(1000000)) 531 pool.resetState() 532 533 // Keep queuing up transactions and make sure all above a limit are dropped 534 for i := uint64(1); i <= maxQueuedPerAccount+5; i++ { 535 if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil { 536 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 537 } 538 if len(pool.pending) != 0 { 539 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 540 } 541 if i <= maxQueuedPerAccount { 542 if pool.queue[account].Len() != int(i) { 543 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 544 } 545 } else { 546 if pool.queue[account].Len() != int(maxQueuedPerAccount) { 547 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), maxQueuedPerAccount) 548 } 549 } 550 } 551 if len(pool.all) != int(maxQueuedPerAccount) { 552 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), maxQueuedPerAccount) 553 } 554 } 555 556 // Tests that if the transaction count belonging to multiple accounts go above 557 // some threshold, the higher transactions are dropped to prevent DOS attacks. 558 func TestTransactionQueueGlobalLimiting(t *testing.T) { 559 // Reduce the queue limits to shorten test time 560 defer func(old uint64) { maxQueuedInTotal = old }(maxQueuedInTotal) 561 maxQueuedInTotal = maxQueuedPerAccount * 3 562 563 // Create the pool to test the limit enforcement with 564 db, _ := ethdb.NewMemDatabase() 565 statedb, _ := state.New(common.Hash{}, db) 566 567 pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) 568 pool.resetState() 569 570 // Create a number of test accounts and fund them 571 state, _ := pool.currentState() 572 573 keys := make([]*ecdsa.PrivateKey, 5) 574 for i := 0; i < len(keys); i++ { 575 keys[i], _ = crypto.GenerateKey() 576 state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 577 } 578 // Generate and queue a batch of transactions 579 nonces := make(map[common.Address]uint64) 580 581 txs := make(types.Transactions, 0, 3*maxQueuedInTotal) 582 for len(txs) < cap(txs) { 583 key := keys[rand.Intn(len(keys))] 584 addr := crypto.PubkeyToAddress(key.PublicKey) 585 586 txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key)) 587 nonces[addr]++ 588 } 589 // Import the batch and verify that limits have been enforced 590 pool.AddBatch(txs) 591 592 queued := 0 593 for addr, list := range pool.queue { 594 if list.Len() > int(maxQueuedPerAccount) { 595 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), maxQueuedPerAccount) 596 } 597 queued += list.Len() 598 } 599 if queued > int(maxQueuedInTotal) { 600 t.Fatalf("total transactions overflow allowance: %d > %d", queued, maxQueuedInTotal) 601 } 602 } 603 604 // Tests that if an account remains idle for a prolonged amount of time, any 605 // non-executable transactions queued up are dropped to prevent wasting resources 606 // on shuffling them around. 607 func TestTransactionQueueTimeLimiting(t *testing.T) { 608 // Reduce the queue limits to shorten test time 609 defer func(old time.Duration) { maxQueuedLifetime = old }(maxQueuedLifetime) 610 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 611 maxQueuedLifetime = time.Second 612 evictionInterval = time.Second 613 614 // Create a test account and fund it 615 pool, key := setupTxPool() 616 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 617 618 state, _ := pool.currentState() 619 state.AddBalance(account, big.NewInt(1000000)) 620 621 // Queue up a batch of transactions 622 for i := uint64(1); i <= maxQueuedPerAccount; i++ { 623 if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil { 624 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 625 } 626 } 627 // Wait until at least two expiration cycles hit and make sure the transactions are gone 628 time.Sleep(2 * evictionInterval) 629 if len(pool.queue) > 0 { 630 t.Fatalf("old transactions remained after eviction") 631 } 632 } 633 634 // Tests that even if the transaction count belonging to a single account goes 635 // above some threshold, as long as the transactions are executable, they are 636 // accepted. 637 func TestTransactionPendingLimiting(t *testing.T) { 638 // Create a test account and fund it 639 pool, key := setupTxPool() 640 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 641 642 state, _ := pool.currentState() 643 state.AddBalance(account, big.NewInt(1000000)) 644 pool.resetState() 645 646 // Keep queuing up transactions and make sure all above a limit are dropped 647 for i := uint64(0); i < maxQueuedPerAccount+5; i++ { 648 if err := pool.Add(transaction(i, big.NewInt(100000), key)); err != nil { 649 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 650 } 651 if pool.pending[account].Len() != int(i)+1 { 652 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 653 } 654 if len(pool.queue) != 0 { 655 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 656 } 657 } 658 if len(pool.all) != int(maxQueuedPerAccount+5) { 659 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), maxQueuedPerAccount+5) 660 } 661 } 662 663 // Tests that the transaction limits are enforced the same way irrelevant whether 664 // the transactions are added one by one or in batches. 665 func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) } 666 func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) } 667 668 func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { 669 // Add a batch of transactions to a pool one by one 670 pool1, key1 := setupTxPool() 671 account1, _ := deriveSender(transaction(0, big.NewInt(0), key1)) 672 state1, _ := pool1.currentState() 673 state1.AddBalance(account1, big.NewInt(1000000)) 674 675 for i := uint64(0); i < maxQueuedPerAccount+5; i++ { 676 if err := pool1.Add(transaction(origin+i, big.NewInt(100000), key1)); err != nil { 677 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 678 } 679 } 680 // Add a batch of transactions to a pool in one big batch 681 pool2, key2 := setupTxPool() 682 account2, _ := deriveSender(transaction(0, big.NewInt(0), key2)) 683 state2, _ := pool2.currentState() 684 state2.AddBalance(account2, big.NewInt(1000000)) 685 686 txns := []*types.Transaction{} 687 for i := uint64(0); i < maxQueuedPerAccount+5; i++ { 688 txns = append(txns, transaction(origin+i, big.NewInt(100000), key2)) 689 } 690 pool2.AddBatch(txns) 691 692 // Ensure the batch optimization honors the same pool mechanics 693 if len(pool1.pending) != len(pool2.pending) { 694 t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending)) 695 } 696 if len(pool1.queue) != len(pool2.queue) { 697 t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue)) 698 } 699 if len(pool1.all) != len(pool2.all) { 700 t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all)) 701 } 702 } 703 704 // Tests that if the transaction count belonging to multiple accounts go above 705 // some hard threshold, the higher transactions are dropped to prevent DOS 706 // attacks. 707 func TestTransactionPendingGlobalLimiting(t *testing.T) { 708 // Reduce the queue limits to shorten test time 709 defer func(old uint64) { maxPendingTotal = old }(maxPendingTotal) 710 maxPendingTotal = minPendingPerAccount * 10 711 712 // Create the pool to test the limit enforcement with 713 db, _ := ethdb.NewMemDatabase() 714 statedb, _ := state.New(common.Hash{}, db) 715 716 pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) 717 pool.resetState() 718 719 // Create a number of test accounts and fund them 720 state, _ := pool.currentState() 721 722 keys := make([]*ecdsa.PrivateKey, 5) 723 for i := 0; i < len(keys); i++ { 724 keys[i], _ = crypto.GenerateKey() 725 state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 726 } 727 // Generate and queue a batch of transactions 728 nonces := make(map[common.Address]uint64) 729 730 txs := types.Transactions{} 731 for _, key := range keys { 732 addr := crypto.PubkeyToAddress(key.PublicKey) 733 for j := 0; j < int(maxPendingTotal)/len(keys)*2; j++ { 734 txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) 735 nonces[addr]++ 736 } 737 } 738 // Import the batch and verify that limits have been enforced 739 pool.AddBatch(txs) 740 741 pending := 0 742 for _, list := range pool.pending { 743 pending += list.Len() 744 } 745 if pending > int(maxPendingTotal) { 746 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, maxPendingTotal) 747 } 748 } 749 750 // Tests that if the transaction count belonging to multiple accounts go above 751 // some hard threshold, if they are under the minimum guaranteed slot count then 752 // the transactions are still kept. 753 func TestTransactionPendingMinimumAllowance(t *testing.T) { 754 // Reduce the queue limits to shorten test time 755 defer func(old uint64) { maxPendingTotal = old }(maxPendingTotal) 756 maxPendingTotal = 0 757 758 // Create the pool to test the limit enforcement with 759 db, _ := ethdb.NewMemDatabase() 760 statedb, _ := state.New(common.Hash{}, db) 761 762 pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) }) 763 pool.resetState() 764 765 // Create a number of test accounts and fund them 766 state, _ := pool.currentState() 767 768 keys := make([]*ecdsa.PrivateKey, 5) 769 for i := 0; i < len(keys); i++ { 770 keys[i], _ = crypto.GenerateKey() 771 state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 772 } 773 // Generate and queue a batch of transactions 774 nonces := make(map[common.Address]uint64) 775 776 txs := types.Transactions{} 777 for _, key := range keys { 778 addr := crypto.PubkeyToAddress(key.PublicKey) 779 for j := 0; j < int(minPendingPerAccount)*2; j++ { 780 txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) 781 nonces[addr]++ 782 } 783 } 784 // Import the batch and verify that limits have been enforced 785 pool.AddBatch(txs) 786 787 for addr, list := range pool.pending { 788 if list.Len() != int(minPendingPerAccount) { 789 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), minPendingPerAccount) 790 } 791 } 792 } 793 794 // Benchmarks the speed of validating the contents of the pending queue of the 795 // transaction pool. 796 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 797 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 798 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 799 800 func benchmarkPendingDemotion(b *testing.B, size int) { 801 // Add a batch of transactions to a pool one by one 802 pool, key := setupTxPool() 803 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 804 state, _ := pool.currentState() 805 state.AddBalance(account, big.NewInt(1000000)) 806 807 for i := 0; i < size; i++ { 808 tx := transaction(uint64(i), big.NewInt(100000), key) 809 pool.promoteTx(account, tx.Hash(), tx) 810 } 811 // Benchmark the speed of pool validation 812 b.ResetTimer() 813 for i := 0; i < b.N; i++ { 814 pool.demoteUnexecutables(state) 815 } 816 } 817 818 // Benchmarks the speed of scheduling the contents of the future queue of the 819 // transaction pool. 820 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 821 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 822 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 823 824 func benchmarkFuturePromotion(b *testing.B, size int) { 825 // Add a batch of transactions to a pool one by one 826 pool, key := setupTxPool() 827 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 828 state, _ := pool.currentState() 829 state.AddBalance(account, big.NewInt(1000000)) 830 831 for i := 0; i < size; i++ { 832 tx := transaction(uint64(1+i), big.NewInt(100000), key) 833 pool.enqueueTx(tx.Hash(), tx) 834 } 835 // Benchmark the speed of pool validation 836 b.ResetTimer() 837 for i := 0; i < b.N; i++ { 838 pool.promoteExecutables(state) 839 } 840 } 841 842 // Benchmarks the speed of iterative transaction insertion. 843 func BenchmarkPoolInsert(b *testing.B) { 844 // Generate a batch of transactions to enqueue into the pool 845 pool, key := setupTxPool() 846 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 847 state, _ := pool.currentState() 848 state.AddBalance(account, big.NewInt(1000000)) 849 850 txs := make(types.Transactions, b.N) 851 for i := 0; i < b.N; i++ { 852 txs[i] = transaction(uint64(i), big.NewInt(100000), key) 853 } 854 // Benchmark importing the transactions into the queue 855 b.ResetTimer() 856 for _, tx := range txs { 857 pool.Add(tx) 858 } 859 } 860 861 // Benchmarks the speed of batched transaction insertion. 862 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 863 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 864 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 865 866 func benchmarkPoolBatchInsert(b *testing.B, size int) { 867 // Generate a batch of transactions to enqueue into the pool 868 pool, key := setupTxPool() 869 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 870 state, _ := pool.currentState() 871 state.AddBalance(account, big.NewInt(1000000)) 872 873 batches := make([]types.Transactions, b.N) 874 for i := 0; i < b.N; i++ { 875 batches[i] = make(types.Transactions, size) 876 for j := 0; j < size; j++ { 877 batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key) 878 } 879 } 880 // Benchmark importing the transactions into the queue 881 b.ResetTimer() 882 for _, batch := range batches { 883 pool.AddBatch(batch) 884 } 885 }