github.com/etherite/go-etherite@v0.0.0-20171015192807-5f4dd87b2f6e/core/tx_pool_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "io/ioutil" 23 "math/big" 24 "math/rand" 25 "os" 26 "testing" 27 "time" 28 29 "github.com/etherite/go-etherite/common" 30 "github.com/etherite/go-etherite/core/state" 31 "github.com/etherite/go-etherite/core/types" 32 "github.com/etherite/go-etherite/crypto" 33 "github.com/etherite/go-etherite/ethdb" 34 "github.com/etherite/go-etherite/event" 35 "github.com/etherite/go-etherite/params" 36 ) 37 38 // testTxPoolConfig is a transaction pool configuration without stateful disk 39 // sideeffects used during testing. 40 var testTxPoolConfig TxPoolConfig 41 42 func init() { 43 testTxPoolConfig = DefaultTxPoolConfig 44 testTxPoolConfig.Journal = "" 45 } 46 47 type testBlockChain struct { 48 statedb *state.StateDB 49 gasLimit *big.Int 50 chainHeadFeed *event.Feed 51 } 52 53 func (bc *testBlockChain) CurrentBlock() *types.Block { 54 return types.NewBlock(&types.Header{ 55 GasLimit: bc.gasLimit, 56 }, nil, nil, nil) 57 } 58 59 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 60 return bc.CurrentBlock() 61 } 62 63 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 64 return bc.statedb, nil 65 } 66 67 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 68 return bc.chainHeadFeed.Subscribe(ch) 69 } 70 71 func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 72 return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) 73 } 74 75 func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 76 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) 77 return tx 78 } 79 80 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 81 db, _ := ethdb.NewMemDatabase() 82 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 83 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 84 85 key, _ := crypto.GenerateKey() 86 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 87 88 return pool, key 89 } 90 91 // validateTxPoolInternals checks various consistency invariants within the pool. 92 func validateTxPoolInternals(pool *TxPool) error { 93 pool.mu.RLock() 94 defer pool.mu.RUnlock() 95 96 // Ensure the total transaction set is consistent with pending + queued 97 pending, queued := pool.stats() 98 if total := len(pool.all); total != pending+queued { 99 return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) 100 } 101 if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { 102 return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued) 103 } 104 // Ensure the next nonce to assign is the correct one 105 for addr, txs := range pool.pending { 106 // Find the last transaction 107 var last uint64 108 for nonce, _ := range txs.txs.items { 109 if last < nonce { 110 last = nonce 111 } 112 } 113 if nonce := pool.pendingState.GetNonce(addr); nonce != last+1 { 114 return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) 115 } 116 } 117 return nil 118 } 119 120 func deriveSender(tx *types.Transaction) (common.Address, error) { 121 return types.Sender(types.HomesteadSigner{}, tx) 122 } 123 124 type testChain struct { 125 *testBlockChain 126 address common.Address 127 trigger *bool 128 } 129 130 // testChain.State() is used multiple times to reset the pending state. 131 // when simulate is true it will create a state that indicates 132 // that tx0 and tx1 are included in the chain. 133 func (c *testChain) State() (*state.StateDB, error) { 134 // delay "state change" by one. The tx pool fetches the 135 // state multiple times and by delaying it a bit we simulate 136 // a state change between those fetches. 137 stdb := c.statedb 138 if *c.trigger { 139 db, _ := ethdb.NewMemDatabase() 140 c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 141 // simulate that the new head block included tx0 and tx1 142 c.statedb.SetNonce(c.address, 2) 143 c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether)) 144 *c.trigger = false 145 } 146 return stdb, nil 147 } 148 149 // This test simulates a scenario where a new block is imported during a 150 // state reset and tests whether the pending state is in sync with the 151 // block head event that initiated the resetState(). 152 func TestStateChangeDuringPoolReset(t *testing.T) { 153 var ( 154 db, _ = ethdb.NewMemDatabase() 155 key, _ = crypto.GenerateKey() 156 address = crypto.PubkeyToAddress(key.PublicKey) 157 statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 158 trigger = false 159 ) 160 161 // setup pool with 2 transaction in it 162 statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether)) 163 blockchain := &testChain{&testBlockChain{statedb, big.NewInt(1000000000), new(event.Feed)}, address, &trigger} 164 165 tx0 := transaction(0, big.NewInt(100000), key) 166 tx1 := transaction(1, big.NewInt(100000), key) 167 168 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 169 defer pool.Stop() 170 171 nonce := pool.State().GetNonce(address) 172 if nonce != 0 { 173 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 174 } 175 176 pool.AddRemotes(types.Transactions{tx0, tx1}) 177 178 nonce = pool.State().GetNonce(address) 179 if nonce != 2 { 180 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 181 } 182 183 // trigger state change in the background 184 trigger = true 185 186 pool.lockedReset(nil, nil) 187 188 pendingTx, err := pool.Pending() 189 if err != nil { 190 t.Fatalf("Could not fetch pending transactions: %v", err) 191 } 192 193 for addr, txs := range pendingTx { 194 t.Logf("%0x: %d\n", addr, len(txs)) 195 } 196 197 nonce = pool.State().GetNonce(address) 198 if nonce != 2 { 199 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 200 } 201 } 202 203 func TestInvalidTransactions(t *testing.T) { 204 pool, key := setupTxPool() 205 defer pool.Stop() 206 207 tx := transaction(0, big.NewInt(100), key) 208 from, _ := deriveSender(tx) 209 210 pool.currentState.AddBalance(from, big.NewInt(1)) 211 if err := pool.AddRemote(tx); err != ErrInsufficientFunds { 212 t.Error("expected", ErrInsufficientFunds) 213 } 214 215 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice())) 216 pool.currentState.AddBalance(from, balance) 217 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 218 t.Error("expected", ErrIntrinsicGas, "got", err) 219 } 220 221 pool.currentState.SetNonce(from, 1) 222 pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) 223 tx = transaction(0, big.NewInt(100000), key) 224 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 225 t.Error("expected", ErrNonceTooLow) 226 } 227 228 tx = transaction(1, big.NewInt(100000), key) 229 pool.gasPrice = big.NewInt(1000) 230 if err := pool.AddRemote(tx); err != ErrUnderpriced { 231 t.Error("expected", ErrUnderpriced, "got", err) 232 } 233 if err := pool.AddLocal(tx); err != nil { 234 t.Error("expected", nil, "got", err) 235 } 236 } 237 238 func TestTransactionQueue(t *testing.T) { 239 pool, key := setupTxPool() 240 defer pool.Stop() 241 242 tx := transaction(0, big.NewInt(100), key) 243 from, _ := deriveSender(tx) 244 pool.currentState.AddBalance(from, big.NewInt(1000)) 245 pool.lockedReset(nil, nil) 246 pool.enqueueTx(tx.Hash(), tx) 247 248 pool.promoteExecutables([]common.Address{from}) 249 if len(pool.pending) != 1 { 250 t.Error("expected valid txs to be 1 is", len(pool.pending)) 251 } 252 253 tx = transaction(1, big.NewInt(100), key) 254 from, _ = deriveSender(tx) 255 pool.currentState.SetNonce(from, 2) 256 pool.enqueueTx(tx.Hash(), tx) 257 pool.promoteExecutables([]common.Address{from}) 258 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 259 t.Error("expected transaction to be in tx pool") 260 } 261 262 if len(pool.queue) > 0 { 263 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 264 } 265 266 pool, key = setupTxPool() 267 defer pool.Stop() 268 269 tx1 := transaction(0, big.NewInt(100), key) 270 tx2 := transaction(10, big.NewInt(100), key) 271 tx3 := transaction(11, big.NewInt(100), key) 272 from, _ = deriveSender(tx1) 273 pool.currentState.AddBalance(from, big.NewInt(1000)) 274 pool.lockedReset(nil, nil) 275 276 pool.enqueueTx(tx1.Hash(), tx1) 277 pool.enqueueTx(tx2.Hash(), tx2) 278 pool.enqueueTx(tx3.Hash(), tx3) 279 280 pool.promoteExecutables([]common.Address{from}) 281 282 if len(pool.pending) != 1 { 283 t.Error("expected tx pool to be 1, got", len(pool.pending)) 284 } 285 if pool.queue[from].Len() != 2 { 286 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 287 } 288 } 289 290 func TestNegativeValue(t *testing.T) { 291 pool, key := setupTxPool() 292 defer pool.Stop() 293 294 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key) 295 from, _ := deriveSender(tx) 296 pool.currentState.AddBalance(from, big.NewInt(1)) 297 if err := pool.AddRemote(tx); err != ErrNegativeValue { 298 t.Error("expected", ErrNegativeValue, "got", err) 299 } 300 } 301 302 func TestTransactionChainFork(t *testing.T) { 303 pool, key := setupTxPool() 304 defer pool.Stop() 305 306 addr := crypto.PubkeyToAddress(key.PublicKey) 307 resetState := func() { 308 db, _ := ethdb.NewMemDatabase() 309 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 310 statedb.AddBalance(addr, big.NewInt(100000000000000)) 311 312 pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 313 pool.lockedReset(nil, nil) 314 } 315 resetState() 316 317 tx := transaction(0, big.NewInt(100000), key) 318 if _, err := pool.add(tx, false); err != nil { 319 t.Error("didn't expect error", err) 320 } 321 pool.removeTx(tx.Hash()) 322 323 // reset the pool's internal state 324 resetState() 325 if _, err := pool.add(tx, false); err != nil { 326 t.Error("didn't expect error", err) 327 } 328 } 329 330 func TestTransactionDoubleNonce(t *testing.T) { 331 pool, key := setupTxPool() 332 defer pool.Stop() 333 334 addr := crypto.PubkeyToAddress(key.PublicKey) 335 resetState := func() { 336 db, _ := ethdb.NewMemDatabase() 337 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 338 statedb.AddBalance(addr, big.NewInt(100000000000000)) 339 340 pool.chain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 341 pool.lockedReset(nil, nil) 342 } 343 resetState() 344 345 signer := types.HomesteadSigner{} 346 tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key) 347 tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key) 348 tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key) 349 350 // Add the first two transaction, ensure higher priced stays only 351 if replace, err := pool.add(tx1, false); err != nil || replace { 352 t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) 353 } 354 if replace, err := pool.add(tx2, false); err != nil || !replace { 355 t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) 356 } 357 pool.promoteExecutables([]common.Address{addr}) 358 if pool.pending[addr].Len() != 1 { 359 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 360 } 361 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 362 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 363 } 364 // Add the third transaction and ensure it's not saved (smaller price) 365 pool.add(tx3, false) 366 pool.promoteExecutables([]common.Address{addr}) 367 if pool.pending[addr].Len() != 1 { 368 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 369 } 370 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 371 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 372 } 373 // Ensure the total transaction count is correct 374 if len(pool.all) != 1 { 375 t.Error("expected 1 total transactions, got", len(pool.all)) 376 } 377 } 378 379 func TestMissingNonce(t *testing.T) { 380 pool, key := setupTxPool() 381 defer pool.Stop() 382 383 addr := crypto.PubkeyToAddress(key.PublicKey) 384 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 385 tx := transaction(1, big.NewInt(100000), key) 386 if _, err := pool.add(tx, false); err != nil { 387 t.Error("didn't expect error", err) 388 } 389 if len(pool.pending) != 0 { 390 t.Error("expected 0 pending transactions, got", len(pool.pending)) 391 } 392 if pool.queue[addr].Len() != 1 { 393 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 394 } 395 if len(pool.all) != 1 { 396 t.Error("expected 1 total transactions, got", len(pool.all)) 397 } 398 } 399 400 func TestTransactionNonceRecovery(t *testing.T) { 401 const n = 10 402 pool, key := setupTxPool() 403 defer pool.Stop() 404 405 addr := crypto.PubkeyToAddress(key.PublicKey) 406 pool.currentState.SetNonce(addr, n) 407 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 408 pool.lockedReset(nil, nil) 409 410 tx := transaction(n, big.NewInt(100000), key) 411 if err := pool.AddRemote(tx); err != nil { 412 t.Error(err) 413 } 414 // simulate some weird re-order of transactions and missing nonce(s) 415 pool.currentState.SetNonce(addr, n-1) 416 pool.lockedReset(nil, nil) 417 if fn := pool.pendingState.GetNonce(addr); fn != n-1 { 418 t.Errorf("expected nonce to be %d, got %d", n-1, fn) 419 } 420 } 421 422 // Tests that if an account runs out of funds, any pending and queued transactions 423 // are dropped. 424 func TestTransactionDropping(t *testing.T) { 425 // Create a test account and fund it 426 pool, key := setupTxPool() 427 defer pool.Stop() 428 429 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 430 pool.currentState.AddBalance(account, big.NewInt(1000)) 431 432 // Add some pending and some queued transactions 433 var ( 434 tx0 = transaction(0, big.NewInt(100), key) 435 tx1 = transaction(1, big.NewInt(200), key) 436 tx2 = transaction(2, big.NewInt(300), key) 437 tx10 = transaction(10, big.NewInt(100), key) 438 tx11 = transaction(11, big.NewInt(200), key) 439 tx12 = transaction(12, big.NewInt(300), key) 440 ) 441 pool.promoteTx(account, tx0.Hash(), tx0) 442 pool.promoteTx(account, tx1.Hash(), tx1) 443 pool.promoteTx(account, tx2.Hash(), tx2) 444 pool.enqueueTx(tx10.Hash(), tx10) 445 pool.enqueueTx(tx11.Hash(), tx11) 446 pool.enqueueTx(tx12.Hash(), tx12) 447 448 // Check that pre and post validations leave the pool as is 449 if pool.pending[account].Len() != 3 { 450 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 451 } 452 if pool.queue[account].Len() != 3 { 453 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 454 } 455 if len(pool.all) != 6 { 456 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 457 } 458 pool.lockedReset(nil, nil) 459 if pool.pending[account].Len() != 3 { 460 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 461 } 462 if pool.queue[account].Len() != 3 { 463 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 464 } 465 if len(pool.all) != 6 { 466 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 467 } 468 // Reduce the balance of the account, and check that invalidated transactions are dropped 469 pool.currentState.AddBalance(account, big.NewInt(-650)) 470 pool.lockedReset(nil, nil) 471 472 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 473 t.Errorf("funded pending transaction missing: %v", tx0) 474 } 475 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { 476 t.Errorf("funded pending transaction missing: %v", tx0) 477 } 478 if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { 479 t.Errorf("out-of-fund pending transaction present: %v", tx1) 480 } 481 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 482 t.Errorf("funded queued transaction missing: %v", tx10) 483 } 484 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { 485 t.Errorf("funded queued transaction missing: %v", tx10) 486 } 487 if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { 488 t.Errorf("out-of-fund queued transaction present: %v", tx11) 489 } 490 if len(pool.all) != 4 { 491 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) 492 } 493 // Reduce the block gas limit, check that invalidated transactions are dropped 494 pool.chain.(*testBlockChain).gasLimit = big.NewInt(100) 495 pool.lockedReset(nil, nil) 496 497 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 498 t.Errorf("funded pending transaction missing: %v", tx0) 499 } 500 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { 501 t.Errorf("over-gased pending transaction present: %v", tx1) 502 } 503 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 504 t.Errorf("funded queued transaction missing: %v", tx10) 505 } 506 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { 507 t.Errorf("over-gased queued transaction present: %v", tx11) 508 } 509 if len(pool.all) != 2 { 510 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2) 511 } 512 } 513 514 // Tests that if a transaction is dropped from the current pending pool (e.g. out 515 // of fund), all consecutive (still valid, but not executable) transactions are 516 // postponed back into the future queue to prevent broadcasting them. 517 func TestTransactionPostponing(t *testing.T) { 518 // Create a test account and fund it 519 pool, key := setupTxPool() 520 defer pool.Stop() 521 522 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 523 pool.currentState.AddBalance(account, big.NewInt(1000)) 524 525 // Add a batch consecutive pending transactions for validation 526 txns := []*types.Transaction{} 527 for i := 0; i < 100; i++ { 528 var tx *types.Transaction 529 if i%2 == 0 { 530 tx = transaction(uint64(i), big.NewInt(100), key) 531 } else { 532 tx = transaction(uint64(i), big.NewInt(500), key) 533 } 534 pool.promoteTx(account, tx.Hash(), tx) 535 txns = append(txns, tx) 536 } 537 // Check that pre and post validations leave the pool as is 538 if pool.pending[account].Len() != len(txns) { 539 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns)) 540 } 541 if len(pool.queue) != 0 { 542 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0) 543 } 544 if len(pool.all) != len(txns) { 545 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)) 546 } 547 pool.lockedReset(nil, nil) 548 if pool.pending[account].Len() != len(txns) { 549 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns)) 550 } 551 if len(pool.queue) != 0 { 552 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0) 553 } 554 if len(pool.all) != len(txns) { 555 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)) 556 } 557 // Reduce the balance of the account, and check that transactions are reorganised 558 pool.currentState.AddBalance(account, big.NewInt(-750)) 559 pool.lockedReset(nil, nil) 560 561 if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok { 562 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0]) 563 } 564 if _, ok := pool.queue[account].txs.items[txns[0].Nonce()]; ok { 565 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0]) 566 } 567 for i, tx := range txns[1:] { 568 if i%2 == 1 { 569 if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok { 570 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 571 } 572 if _, ok := pool.queue[account].txs.items[tx.Nonce()]; !ok { 573 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 574 } 575 } else { 576 if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok { 577 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 578 } 579 if _, ok := pool.queue[account].txs.items[tx.Nonce()]; ok { 580 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 581 } 582 } 583 } 584 if len(pool.all) != len(txns)/2 { 585 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)/2) 586 } 587 } 588 589 // Tests that if the transaction count belonging to a single account goes above 590 // some threshold, the higher transactions are dropped to prevent DOS attacks. 591 func TestTransactionQueueAccountLimiting(t *testing.T) { 592 // Create a test account and fund it 593 pool, key := setupTxPool() 594 defer pool.Stop() 595 596 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 597 pool.currentState.AddBalance(account, big.NewInt(1000000)) 598 599 // Keep queuing up transactions and make sure all above a limit are dropped 600 for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { 601 if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil { 602 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 603 } 604 if len(pool.pending) != 0 { 605 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 606 } 607 if i <= testTxPoolConfig.AccountQueue { 608 if pool.queue[account].Len() != int(i) { 609 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 610 } 611 } else { 612 if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) { 613 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue) 614 } 615 } 616 } 617 if len(pool.all) != int(testTxPoolConfig.AccountQueue) { 618 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue) 619 } 620 } 621 622 // Tests that if the transaction count belonging to multiple accounts go above 623 // some threshold, the higher transactions are dropped to prevent DOS attacks. 624 // 625 // This logic should not hold for local transactions, unless the local tracking 626 // mechanism is disabled. 627 func TestTransactionQueueGlobalLimiting(t *testing.T) { 628 testTransactionQueueGlobalLimiting(t, false) 629 } 630 func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { 631 testTransactionQueueGlobalLimiting(t, true) 632 } 633 634 func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { 635 // Create the pool to test the limit enforcement with 636 db, _ := ethdb.NewMemDatabase() 637 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 638 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 639 640 config := testTxPoolConfig 641 config.NoLocals = nolocals 642 config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible) 643 644 pool := NewTxPool(config, params.TestChainConfig, blockchain) 645 defer pool.Stop() 646 647 // Create a number of test accounts and fund them (last one will be the local) 648 keys := make([]*ecdsa.PrivateKey, 5) 649 for i := 0; i < len(keys); i++ { 650 keys[i], _ = crypto.GenerateKey() 651 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 652 } 653 local := keys[len(keys)-1] 654 655 // Generate and queue a batch of transactions 656 nonces := make(map[common.Address]uint64) 657 658 txs := make(types.Transactions, 0, 3*config.GlobalQueue) 659 for len(txs) < cap(txs) { 660 key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account 661 addr := crypto.PubkeyToAddress(key.PublicKey) 662 663 txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key)) 664 nonces[addr]++ 665 } 666 // Import the batch and verify that limits have been enforced 667 pool.AddRemotes(txs) 668 669 queued := 0 670 for addr, list := range pool.queue { 671 if list.Len() > int(config.AccountQueue) { 672 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 673 } 674 queued += list.Len() 675 } 676 if queued > int(config.GlobalQueue) { 677 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 678 } 679 // Generate a batch of transactions from the local account and import them 680 txs = txs[:0] 681 for i := uint64(0); i < 3*config.GlobalQueue; i++ { 682 txs = append(txs, transaction(i+1, big.NewInt(100000), local)) 683 } 684 pool.AddLocals(txs) 685 686 // If locals are disabled, the previous eviction algorithm should apply here too 687 if nolocals { 688 queued := 0 689 for addr, list := range pool.queue { 690 if list.Len() > int(config.AccountQueue) { 691 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 692 } 693 queued += list.Len() 694 } 695 if queued > int(config.GlobalQueue) { 696 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 697 } 698 } else { 699 // Local exemptions are enabled, make sure the local account owned the queue 700 if len(pool.queue) != 1 { 701 t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) 702 } 703 // Also ensure no local transactions are ever dropped, even if above global limits 704 if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { 705 t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) 706 } 707 } 708 } 709 710 // Tests that if an account remains idle for a prolonged amount of time, any 711 // non-executable transactions queued up are dropped to prevent wasting resources 712 // on shuffling them around. 713 // 714 // This logic should not hold for local transactions, unless the local tracking 715 // mechanism is disabled. 716 func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) } 717 func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { testTransactionQueueTimeLimiting(t, true) } 718 719 func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { 720 // Reduce the eviction interval to a testable amount 721 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 722 evictionInterval = time.Second 723 724 // Create the pool to test the non-expiration enforcement 725 db, _ := ethdb.NewMemDatabase() 726 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 727 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 728 729 config := testTxPoolConfig 730 config.Lifetime = time.Second 731 config.NoLocals = nolocals 732 733 pool := NewTxPool(config, params.TestChainConfig, blockchain) 734 defer pool.Stop() 735 736 // Create two test accounts to ensure remotes expire but locals do not 737 local, _ := crypto.GenerateKey() 738 remote, _ := crypto.GenerateKey() 739 740 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 741 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 742 743 // Add the two transactions and ensure they both are queued up 744 if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil { 745 t.Fatalf("failed to add local transaction: %v", err) 746 } 747 if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil { 748 t.Fatalf("failed to add remote transaction: %v", err) 749 } 750 pending, queued := pool.Stats() 751 if pending != 0 { 752 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 753 } 754 if queued != 2 { 755 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 756 } 757 if err := validateTxPoolInternals(pool); err != nil { 758 t.Fatalf("pool internal state corrupted: %v", err) 759 } 760 // Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains 761 time.Sleep(2 * config.Lifetime) 762 763 pending, queued = pool.Stats() 764 if pending != 0 { 765 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 766 } 767 if nolocals { 768 if queued != 0 { 769 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 770 } 771 } else { 772 if queued != 1 { 773 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 774 } 775 } 776 if err := validateTxPoolInternals(pool); err != nil { 777 t.Fatalf("pool internal state corrupted: %v", err) 778 } 779 } 780 781 // Tests that even if the transaction count belonging to a single account goes 782 // above some threshold, as long as the transactions are executable, they are 783 // accepted. 784 func TestTransactionPendingLimiting(t *testing.T) { 785 // Create a test account and fund it 786 pool, key := setupTxPool() 787 defer pool.Stop() 788 789 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 790 pool.currentState.AddBalance(account, big.NewInt(1000000)) 791 792 // Keep queuing up transactions and make sure all above a limit are dropped 793 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 794 if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil { 795 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 796 } 797 if pool.pending[account].Len() != int(i)+1 { 798 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 799 } 800 if len(pool.queue) != 0 { 801 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 802 } 803 } 804 if len(pool.all) != int(testTxPoolConfig.AccountQueue+5) { 805 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5) 806 } 807 } 808 809 // Tests that the transaction limits are enforced the same way irrelevant whether 810 // the transactions are added one by one or in batches. 811 func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) } 812 func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) } 813 814 func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { 815 // Add a batch of transactions to a pool one by one 816 pool1, key1 := setupTxPool() 817 defer pool1.Stop() 818 819 account1, _ := deriveSender(transaction(0, big.NewInt(0), key1)) 820 pool1.currentState.AddBalance(account1, big.NewInt(1000000)) 821 822 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 823 if err := pool1.AddRemote(transaction(origin+i, big.NewInt(100000), key1)); err != nil { 824 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 825 } 826 } 827 // Add a batch of transactions to a pool in one big batch 828 pool2, key2 := setupTxPool() 829 defer pool2.Stop() 830 831 account2, _ := deriveSender(transaction(0, big.NewInt(0), key2)) 832 pool2.currentState.AddBalance(account2, big.NewInt(1000000)) 833 834 txns := []*types.Transaction{} 835 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 836 txns = append(txns, transaction(origin+i, big.NewInt(100000), key2)) 837 } 838 pool2.AddRemotes(txns) 839 840 // Ensure the batch optimization honors the same pool mechanics 841 if len(pool1.pending) != len(pool2.pending) { 842 t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending)) 843 } 844 if len(pool1.queue) != len(pool2.queue) { 845 t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue)) 846 } 847 if len(pool1.all) != len(pool2.all) { 848 t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all)) 849 } 850 if err := validateTxPoolInternals(pool1); err != nil { 851 t.Errorf("pool 1 internal state corrupted: %v", err) 852 } 853 if err := validateTxPoolInternals(pool2); err != nil { 854 t.Errorf("pool 2 internal state corrupted: %v", err) 855 } 856 } 857 858 // Tests that if the transaction count belonging to multiple accounts go above 859 // some hard threshold, the higher transactions are dropped to prevent DOS 860 // attacks. 861 func TestTransactionPendingGlobalLimiting(t *testing.T) { 862 // Create the pool to test the limit enforcement with 863 db, _ := ethdb.NewMemDatabase() 864 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 865 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 866 867 config := testTxPoolConfig 868 config.GlobalSlots = config.AccountSlots * 10 869 870 pool := NewTxPool(config, params.TestChainConfig, blockchain) 871 defer pool.Stop() 872 873 // Create a number of test accounts and fund them 874 keys := make([]*ecdsa.PrivateKey, 5) 875 for i := 0; i < len(keys); i++ { 876 keys[i], _ = crypto.GenerateKey() 877 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 878 } 879 // Generate and queue a batch of transactions 880 nonces := make(map[common.Address]uint64) 881 882 txs := types.Transactions{} 883 for _, key := range keys { 884 addr := crypto.PubkeyToAddress(key.PublicKey) 885 for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { 886 txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) 887 nonces[addr]++ 888 } 889 } 890 // Import the batch and verify that limits have been enforced 891 pool.AddRemotes(txs) 892 893 pending := 0 894 for _, list := range pool.pending { 895 pending += list.Len() 896 } 897 if pending > int(config.GlobalSlots) { 898 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) 899 } 900 if err := validateTxPoolInternals(pool); err != nil { 901 t.Fatalf("pool internal state corrupted: %v", err) 902 } 903 } 904 905 // Tests that if transactions start being capped, transactions are also removed from 'all' 906 func TestTransactionCapClearsFromAll(t *testing.T) { 907 // Create the pool to test the limit enforcement with 908 db, _ := ethdb.NewMemDatabase() 909 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 910 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 911 912 config := testTxPoolConfig 913 config.AccountSlots = 2 914 config.AccountQueue = 2 915 config.GlobalSlots = 8 916 917 pool := NewTxPool(config, params.TestChainConfig, blockchain) 918 defer pool.Stop() 919 920 // Create a number of test accounts and fund them 921 key, _ := crypto.GenerateKey() 922 addr := crypto.PubkeyToAddress(key.PublicKey) 923 pool.currentState.AddBalance(addr, big.NewInt(1000000)) 924 925 txs := types.Transactions{} 926 for j := 0; j < int(config.GlobalSlots)*2; j++ { 927 txs = append(txs, transaction(uint64(j), big.NewInt(100000), key)) 928 } 929 // Import the batch and verify that limits have been enforced 930 pool.AddRemotes(txs) 931 if err := validateTxPoolInternals(pool); err != nil { 932 t.Fatalf("pool internal state corrupted: %v", err) 933 } 934 } 935 936 // Tests that if the transaction count belonging to multiple accounts go above 937 // some hard threshold, if they are under the minimum guaranteed slot count then 938 // the transactions are still kept. 939 func TestTransactionPendingMinimumAllowance(t *testing.T) { 940 // Create the pool to test the limit enforcement with 941 db, _ := ethdb.NewMemDatabase() 942 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 943 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 944 945 config := testTxPoolConfig 946 config.GlobalSlots = 0 947 948 pool := NewTxPool(config, params.TestChainConfig, blockchain) 949 defer pool.Stop() 950 951 // Create a number of test accounts and fund them 952 keys := make([]*ecdsa.PrivateKey, 5) 953 for i := 0; i < len(keys); i++ { 954 keys[i], _ = crypto.GenerateKey() 955 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 956 } 957 // Generate and queue a batch of transactions 958 nonces := make(map[common.Address]uint64) 959 960 txs := types.Transactions{} 961 for _, key := range keys { 962 addr := crypto.PubkeyToAddress(key.PublicKey) 963 for j := 0; j < int(config.AccountSlots)*2; j++ { 964 txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key)) 965 nonces[addr]++ 966 } 967 } 968 // Import the batch and verify that limits have been enforced 969 pool.AddRemotes(txs) 970 971 for addr, list := range pool.pending { 972 if list.Len() != int(config.AccountSlots) { 973 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) 974 } 975 } 976 if err := validateTxPoolInternals(pool); err != nil { 977 t.Fatalf("pool internal state corrupted: %v", err) 978 } 979 } 980 981 // Tests that setting the transaction pool gas price to a higher value correctly 982 // discards everything cheaper than that and moves any gapped transactions back 983 // from the pending pool to the queue. 984 // 985 // Note, local transactions are never allowed to be dropped. 986 func TestTransactionPoolRepricing(t *testing.T) { 987 // Create the pool to test the pricing enforcement with 988 db, _ := ethdb.NewMemDatabase() 989 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 990 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 991 992 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 993 defer pool.Stop() 994 995 // Create a number of test accounts and fund them 996 keys := make([]*ecdsa.PrivateKey, 3) 997 for i := 0; i < len(keys); i++ { 998 keys[i], _ = crypto.GenerateKey() 999 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1000 } 1001 // Generate and queue a batch of transactions, both pending and queued 1002 txs := types.Transactions{} 1003 1004 txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(2), keys[0])) 1005 txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])) 1006 txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(2), keys[0])) 1007 1008 txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[1])) 1009 txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])) 1010 txs = append(txs, pricedTransaction(3, big.NewInt(100000), big.NewInt(2), keys[1])) 1011 1012 ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2]) 1013 1014 // Import the batch and that both pending and queued transactions match up 1015 pool.AddRemotes(txs) 1016 pool.AddLocal(ltx) 1017 1018 pending, queued := pool.Stats() 1019 if pending != 4 { 1020 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1021 } 1022 if queued != 3 { 1023 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1024 } 1025 if err := validateTxPoolInternals(pool); err != nil { 1026 t.Fatalf("pool internal state corrupted: %v", err) 1027 } 1028 // Reprice the pool and check that underpriced transactions get dropped 1029 pool.SetGasPrice(big.NewInt(2)) 1030 1031 pending, queued = pool.Stats() 1032 if pending != 2 { 1033 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1034 } 1035 if queued != 3 { 1036 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1037 } 1038 if err := validateTxPoolInternals(pool); err != nil { 1039 t.Fatalf("pool internal state corrupted: %v", err) 1040 } 1041 // Check that we can't add the old transactions back 1042 if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])); err != ErrUnderpriced { 1043 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1044 } 1045 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced { 1046 t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1047 } 1048 if err := validateTxPoolInternals(pool); err != nil { 1049 t.Fatalf("pool internal state corrupted: %v", err) 1050 } 1051 // However we can add local underpriced transactions 1052 tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[2]) 1053 if err := pool.AddLocal(tx); err != nil { 1054 t.Fatalf("failed to add underpriced local transaction: %v", err) 1055 } 1056 if pending, _ = pool.Stats(); pending != 3 { 1057 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1058 } 1059 if err := validateTxPoolInternals(pool); err != nil { 1060 t.Fatalf("pool internal state corrupted: %v", err) 1061 } 1062 } 1063 1064 // Tests that setting the transaction pool gas price to a higher value does not 1065 // remove local transactions. 1066 func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { 1067 // Create the pool to test the pricing enforcement with 1068 db, _ := ethdb.NewMemDatabase() 1069 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1070 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1071 1072 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1073 defer pool.Stop() 1074 1075 // Create a number of test accounts and fund them 1076 keys := make([]*ecdsa.PrivateKey, 3) 1077 for i := 0; i < len(keys); i++ { 1078 keys[i], _ = crypto.GenerateKey() 1079 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) 1080 } 1081 // Create transaction (both pending and queued) with a linearly growing gasprice 1082 for i := uint64(0); i < 500; i++ { 1083 // Add pending 1084 p_tx := pricedTransaction(i, big.NewInt(100000), big.NewInt(int64(i)), keys[2]) 1085 if err := pool.AddLocal(p_tx); err != nil { 1086 t.Fatal(err) 1087 } 1088 // Add queued 1089 q_tx := pricedTransaction(i+501, big.NewInt(100000), big.NewInt(int64(i)), keys[2]) 1090 if err := pool.AddLocal(q_tx); err != nil { 1091 t.Fatal(err) 1092 } 1093 } 1094 pending, queued := pool.Stats() 1095 expPending, expQueued := 500, 500 1096 validate := func() { 1097 pending, queued = pool.Stats() 1098 if pending != expPending { 1099 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) 1100 } 1101 if queued != expQueued { 1102 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) 1103 } 1104 1105 if err := validateTxPoolInternals(pool); err != nil { 1106 t.Fatalf("pool internal state corrupted: %v", err) 1107 } 1108 } 1109 validate() 1110 1111 // Reprice the pool and check that nothing is dropped 1112 pool.SetGasPrice(big.NewInt(2)) 1113 validate() 1114 1115 pool.SetGasPrice(big.NewInt(2)) 1116 pool.SetGasPrice(big.NewInt(4)) 1117 pool.SetGasPrice(big.NewInt(8)) 1118 pool.SetGasPrice(big.NewInt(100)) 1119 validate() 1120 } 1121 1122 // Tests that when the pool reaches its global transaction limit, underpriced 1123 // transactions are gradually shifted out for more expensive ones and any gapped 1124 // pending transactions are moved into te queue. 1125 // 1126 // Note, local transactions are never allowed to be dropped. 1127 func TestTransactionPoolUnderpricing(t *testing.T) { 1128 // Create the pool to test the pricing enforcement with 1129 db, _ := ethdb.NewMemDatabase() 1130 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1131 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1132 1133 config := testTxPoolConfig 1134 config.GlobalSlots = 2 1135 config.GlobalQueue = 2 1136 1137 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1138 defer pool.Stop() 1139 1140 // Create a number of test accounts and fund them 1141 keys := make([]*ecdsa.PrivateKey, 3) 1142 for i := 0; i < len(keys); i++ { 1143 keys[i], _ = crypto.GenerateKey() 1144 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1145 } 1146 // Generate and queue a batch of transactions, both pending and queued 1147 txs := types.Transactions{} 1148 1149 txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0])) 1150 txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[0])) 1151 1152 txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[1])) 1153 1154 ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2]) 1155 1156 // Import the batch and that both pending and queued transactions match up 1157 pool.AddRemotes(txs) 1158 pool.AddLocal(ltx) 1159 1160 pending, queued := pool.Stats() 1161 if pending != 3 { 1162 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1163 } 1164 if queued != 1 { 1165 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1166 } 1167 if err := validateTxPoolInternals(pool); err != nil { 1168 t.Fatalf("pool internal state corrupted: %v", err) 1169 } 1170 // Ensure that adding an underpriced transaction on block limit fails 1171 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced { 1172 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1173 } 1174 // Ensure that adding high priced transactions drops cheap ones, but not own 1175 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(3), keys[1])); err != nil { 1176 t.Fatalf("failed to add well priced transaction: %v", err) 1177 } 1178 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(4), keys[1])); err != nil { 1179 t.Fatalf("failed to add well priced transaction: %v", err) 1180 } 1181 if err := pool.AddRemote(pricedTransaction(3, big.NewInt(100000), big.NewInt(5), keys[1])); err != nil { 1182 t.Fatalf("failed to add well priced transaction: %v", err) 1183 } 1184 pending, queued = pool.Stats() 1185 if pending != 2 { 1186 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1187 } 1188 if queued != 2 { 1189 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1190 } 1191 if err := validateTxPoolInternals(pool); err != nil { 1192 t.Fatalf("pool internal state corrupted: %v", err) 1193 } 1194 // Ensure that adding local transactions can push out even higher priced ones 1195 tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(0), keys[2]) 1196 if err := pool.AddLocal(tx); err != nil { 1197 t.Fatalf("failed to add underpriced local transaction: %v", err) 1198 } 1199 pending, queued = pool.Stats() 1200 if pending != 2 { 1201 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1202 } 1203 if queued != 2 { 1204 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1205 } 1206 if err := validateTxPoolInternals(pool); err != nil { 1207 t.Fatalf("pool internal state corrupted: %v", err) 1208 } 1209 } 1210 1211 // Tests that the pool rejects replacement transactions that don't meet the minimum 1212 // price bump required. 1213 func TestTransactionReplacement(t *testing.T) { 1214 // Create the pool to test the pricing enforcement with 1215 db, _ := ethdb.NewMemDatabase() 1216 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1217 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1218 1219 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) 1220 defer pool.Stop() 1221 1222 // Create a test account to add transactions with 1223 key, _ := crypto.GenerateKey() 1224 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1225 1226 // Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1227 price := int64(100) 1228 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 1229 1230 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), key)); err != nil { 1231 t.Fatalf("failed to add original cheap pending transaction: %v", err) 1232 } 1233 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1234 t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1235 } 1236 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(2), key)); err != nil { 1237 t.Fatalf("failed to replace original cheap pending transaction: %v", err) 1238 } 1239 1240 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(price), key)); err != nil { 1241 t.Fatalf("failed to add original proper pending transaction: %v", err) 1242 } 1243 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold), key)); err != ErrReplaceUnderpriced { 1244 t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1245 } 1246 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold+1), key)); err != nil { 1247 t.Fatalf("failed to replace original proper pending transaction: %v", err) 1248 } 1249 // Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too) 1250 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), key)); err != nil { 1251 t.Fatalf("failed to add original queued transaction: %v", err) 1252 } 1253 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1254 t.Fatalf("original queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1255 } 1256 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(2), key)); err != nil { 1257 t.Fatalf("failed to replace original queued transaction: %v", err) 1258 } 1259 1260 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(price), key)); err != nil { 1261 t.Fatalf("failed to add original queued transaction: %v", err) 1262 } 1263 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(threshold), key)); err != ErrReplaceUnderpriced { 1264 t.Fatalf("original queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1265 } 1266 if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(threshold+1), key)); err != nil { 1267 t.Fatalf("failed to replace original queued transaction: %v", err) 1268 } 1269 if err := validateTxPoolInternals(pool); err != nil { 1270 t.Fatalf("pool internal state corrupted: %v", err) 1271 } 1272 } 1273 1274 // Tests that local transactions are journaled to disk, but remote transactions 1275 // get discarded between restarts. 1276 func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } 1277 func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } 1278 1279 func testTransactionJournaling(t *testing.T, nolocals bool) { 1280 // Create a temporary file for the journal 1281 file, err := ioutil.TempFile("", "") 1282 if err != nil { 1283 t.Fatalf("failed to create temporary journal: %v", err) 1284 } 1285 journal := file.Name() 1286 defer os.Remove(journal) 1287 1288 // Clean up the temporary file, we only need the path for now 1289 file.Close() 1290 os.Remove(journal) 1291 1292 // Create the original pool to inject transaction into the journal 1293 db, _ := ethdb.NewMemDatabase() 1294 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1295 blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1296 1297 config := testTxPoolConfig 1298 config.NoLocals = nolocals 1299 config.Journal = journal 1300 config.Rejournal = time.Second 1301 1302 pool := NewTxPool(config, params.TestChainConfig, blockchain) 1303 1304 // Create two test accounts to ensure remotes expire but locals do not 1305 local, _ := crypto.GenerateKey() 1306 remote, _ := crypto.GenerateKey() 1307 1308 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1309 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1310 1311 // Add three local and a remote transactions and ensure they are queued up 1312 if err := pool.AddLocal(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), local)); err != nil { 1313 t.Fatalf("failed to add local transaction: %v", err) 1314 } 1315 if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil { 1316 t.Fatalf("failed to add local transaction: %v", err) 1317 } 1318 if err := pool.AddLocal(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), local)); err != nil { 1319 t.Fatalf("failed to add local transaction: %v", err) 1320 } 1321 if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), remote)); err != nil { 1322 t.Fatalf("failed to add remote transaction: %v", err) 1323 } 1324 pending, queued := pool.Stats() 1325 if pending != 4 { 1326 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1327 } 1328 if queued != 0 { 1329 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1330 } 1331 if err := validateTxPoolInternals(pool); err != nil { 1332 t.Fatalf("pool internal state corrupted: %v", err) 1333 } 1334 // Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive 1335 pool.Stop() 1336 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1337 blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1338 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1339 1340 pending, queued = pool.Stats() 1341 if queued != 0 { 1342 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1343 } 1344 if nolocals { 1345 if pending != 0 { 1346 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1347 } 1348 } else { 1349 if pending != 2 { 1350 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1351 } 1352 } 1353 if err := validateTxPoolInternals(pool); err != nil { 1354 t.Fatalf("pool internal state corrupted: %v", err) 1355 } 1356 // Bump the nonce temporarily and ensure the newly invalidated transaction is removed 1357 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) 1358 pool.lockedReset(nil, nil) 1359 time.Sleep(2 * config.Rejournal) 1360 pool.Stop() 1361 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1362 blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed)} 1363 pool = NewTxPool(config, params.TestChainConfig, blockchain) 1364 1365 pending, queued = pool.Stats() 1366 if pending != 0 { 1367 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1368 } 1369 if nolocals { 1370 if queued != 0 { 1371 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1372 } 1373 } else { 1374 if queued != 1 { 1375 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1376 } 1377 } 1378 if err := validateTxPoolInternals(pool); err != nil { 1379 t.Fatalf("pool internal state corrupted: %v", err) 1380 } 1381 pool.Stop() 1382 } 1383 1384 // Benchmarks the speed of validating the contents of the pending queue of the 1385 // transaction pool. 1386 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 1387 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 1388 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 1389 1390 func benchmarkPendingDemotion(b *testing.B, size int) { 1391 // Add a batch of transactions to a pool one by one 1392 pool, key := setupTxPool() 1393 defer pool.Stop() 1394 1395 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 1396 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1397 1398 for i := 0; i < size; i++ { 1399 tx := transaction(uint64(i), big.NewInt(100000), key) 1400 pool.promoteTx(account, tx.Hash(), tx) 1401 } 1402 // Benchmark the speed of pool validation 1403 b.ResetTimer() 1404 for i := 0; i < b.N; i++ { 1405 pool.demoteUnexecutables() 1406 } 1407 } 1408 1409 // Benchmarks the speed of scheduling the contents of the future queue of the 1410 // transaction pool. 1411 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 1412 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 1413 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 1414 1415 func benchmarkFuturePromotion(b *testing.B, size int) { 1416 // Add a batch of transactions to a pool one by one 1417 pool, key := setupTxPool() 1418 defer pool.Stop() 1419 1420 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 1421 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1422 1423 for i := 0; i < size; i++ { 1424 tx := transaction(uint64(1+i), big.NewInt(100000), key) 1425 pool.enqueueTx(tx.Hash(), tx) 1426 } 1427 // Benchmark the speed of pool validation 1428 b.ResetTimer() 1429 for i := 0; i < b.N; i++ { 1430 pool.promoteExecutables(nil) 1431 } 1432 } 1433 1434 // Benchmarks the speed of iterative transaction insertion. 1435 func BenchmarkPoolInsert(b *testing.B) { 1436 // Generate a batch of transactions to enqueue into the pool 1437 pool, key := setupTxPool() 1438 defer pool.Stop() 1439 1440 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 1441 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1442 1443 txs := make(types.Transactions, b.N) 1444 for i := 0; i < b.N; i++ { 1445 txs[i] = transaction(uint64(i), big.NewInt(100000), key) 1446 } 1447 // Benchmark importing the transactions into the queue 1448 b.ResetTimer() 1449 for _, tx := range txs { 1450 pool.AddRemote(tx) 1451 } 1452 } 1453 1454 // Benchmarks the speed of batched transaction insertion. 1455 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 1456 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 1457 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 1458 1459 func benchmarkPoolBatchInsert(b *testing.B, size int) { 1460 // Generate a batch of transactions to enqueue into the pool 1461 pool, key := setupTxPool() 1462 defer pool.Stop() 1463 1464 account, _ := deriveSender(transaction(0, big.NewInt(0), key)) 1465 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1466 1467 batches := make([]types.Transactions, b.N) 1468 for i := 0; i < b.N; i++ { 1469 batches[i] = make(types.Transactions, size) 1470 for j := 0; j < size; j++ { 1471 batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key) 1472 } 1473 } 1474 // Benchmark importing the transactions into the queue 1475 b.ResetTimer() 1476 for _, batch := range batches { 1477 pool.AddRemotes(batch) 1478 } 1479 }