github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/core/tx_pool_test.go (about) 1 package core 2 3 import ( 4 "crypto/ecdsa" 5 "fmt" 6 "io/ioutil" 7 "math/big" 8 "math/rand" 9 "os" 10 "testing" 11 "time" 12 13 "github.com/neatio-net/neatio/chain/core/rawdb" 14 "github.com/neatio-net/neatio/chain/core/state" 15 "github.com/neatio-net/neatio/chain/core/types" 16 "github.com/neatio-net/neatio/params" 17 "github.com/neatio-net/neatio/utilities/common" 18 "github.com/neatio-net/neatio/utilities/crypto" 19 "github.com/neatio-net/neatio/utilities/event" 20 ) 21 22 var testTxPoolConfig TxPoolConfig 23 24 func init() { 25 testTxPoolConfig = DefaultTxPoolConfig 26 testTxPoolConfig.Journal = "" 27 } 28 29 type testBlockChain struct { 30 statedb *state.StateDB 31 gasLimit uint64 32 chainHeadFeed *event.Feed 33 } 34 35 func (bc *testBlockChain) CurrentBlock() *types.Block { 36 return types.NewBlock(&types.Header{ 37 GasLimit: bc.gasLimit, 38 }, nil, nil, nil) 39 } 40 41 func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { 42 return bc.CurrentBlock() 43 } 44 45 func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { 46 return bc.statedb, nil 47 } 48 49 func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { 50 return bc.chainHeadFeed.Subscribe(ch) 51 } 52 53 func transaction(nonce uint64, gaslimit uint64, key *ecdsa.PrivateKey) *types.Transaction { 54 return pricedTransaction(nonce, gaslimit, big.NewInt(1), key) 55 } 56 57 func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction { 58 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key) 59 return tx 60 } 61 62 func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { 63 diskdb := rawdb.NewMemoryDatabase() 64 statedb, _ := state.New(common.Hash{}, state.NewDatabase(diskdb)) 65 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 66 67 key, _ := crypto.GenerateKey() 68 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 69 70 return pool, key 71 } 72 73 func validateTxPoolInternals(pool *TxPool) error { 74 pool.mu.RLock() 75 defer pool.mu.RUnlock() 76 77 pending, queued := pool.stats() 78 if total := len(pool.all); total != pending+queued { 79 return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued) 80 } 81 if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued { 82 return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued) 83 } 84 for addr, txs := range pool.pending { 85 var last uint64 86 for nonce := range txs.txs.items { 87 if last < nonce { 88 last = nonce 89 } 90 } 91 if nonce := pool.pendingState.GetNonce(addr); nonce != last+1 { 92 return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1) 93 } 94 } 95 return nil 96 } 97 98 func validateEvents(events chan TxPreEvent, count int) error { 99 for i := 0; i < count; i++ { 100 select { 101 case <-events: 102 case <-time.After(time.Second): 103 return fmt.Errorf("event #%d not fired", i) 104 } 105 } 106 select { 107 case tx := <-events: 108 return fmt.Errorf("more than %d events fired: %v", count, tx.Tx) 109 110 case <-time.After(50 * time.Millisecond): 111 } 112 return nil 113 } 114 115 func deriveSender(tx *types.Transaction) (common.Address, error) { 116 return types.Sender(types.HomesteadSigner{}, tx) 117 } 118 119 type testChain struct { 120 *testBlockChain 121 address common.Address 122 trigger *bool 123 } 124 125 func (c *testChain) State() (*state.StateDB, error) { 126 stdb := c.statedb 127 if *c.trigger { 128 db := rawdb.NewMemoryDatabase() 129 c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 130 c.statedb.SetNonce(c.address, 2) 131 c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Nio)) 132 *c.trigger = false 133 } 134 return stdb, nil 135 } 136 137 func TestStateChangeDuringTransactionPoolReset(t *testing.T) { 138 t.Parallel() 139 140 var ( 141 db = rawdb.NewMemoryDatabase() 142 key, _ = crypto.GenerateKey() 143 address = crypto.PubkeyToAddress(key.PublicKey) 144 statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 145 trigger = false 146 ) 147 148 statedb.SetBalance(address, new(big.Int).SetUint64(params.Nio)) 149 blockchain := &testChain{&testBlockChain{statedb, 1000000000, new(event.Feed)}, address, &trigger} 150 151 tx0 := transaction(0, 100000, key) 152 tx1 := transaction(1, 100000, key) 153 154 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 155 defer pool.Stop() 156 157 nonce := pool.State().GetNonce(address) 158 if nonce != 0 { 159 t.Fatalf("Invalid nonce, want 0, got %d", nonce) 160 } 161 162 pool.AddRemotes(types.Transactions{tx0, tx1}) 163 164 nonce = pool.State().GetNonce(address) 165 if nonce != 2 { 166 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 167 } 168 169 // trigger state change in the background 170 trigger = true 171 172 pool.lockedReset(nil, nil) 173 174 pendingTx, err := pool.Pending() 175 if err != nil { 176 t.Fatalf("Could not fetch pending transactions: %v", err) 177 } 178 179 for addr, txs := range pendingTx { 180 t.Logf("%0x: %d\n", addr, len(txs)) 181 } 182 183 nonce = pool.State().GetNonce(address) 184 if nonce != 2 { 185 t.Fatalf("Invalid nonce, want 2, got %d", nonce) 186 } 187 } 188 189 func TestInvalidTransactions(t *testing.T) { 190 t.Parallel() 191 192 pool, key := setupTxPool() 193 defer pool.Stop() 194 195 tx := transaction(0, 100, key) 196 from, _ := deriveSender(tx) 197 198 pool.currentState.AddBalance(from, big.NewInt(1)) 199 if err := pool.AddRemote(tx); err != ErrInsufficientFunds { 200 t.Error("expected", ErrInsufficientFunds) 201 } 202 203 balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) 204 pool.currentState.AddBalance(from, balance) 205 if err := pool.AddRemote(tx); err != ErrIntrinsicGas { 206 t.Error("expected", ErrIntrinsicGas, "got", err) 207 } 208 209 pool.currentState.SetNonce(from, 1) 210 pool.currentState.AddBalance(from, big.NewInt(0xffffffffffffff)) 211 tx = transaction(0, 100000, key) 212 if err := pool.AddRemote(tx); err != ErrNonceTooLow { 213 t.Error("expected", ErrNonceTooLow) 214 } 215 216 tx = transaction(1, 100000, key) 217 pool.gasPrice = big.NewInt(1000) 218 if err := pool.AddRemote(tx); err != ErrUnderpriced { 219 t.Error("expected", ErrUnderpriced, "got", err) 220 } 221 if err := pool.AddLocal(tx); err != nil { 222 t.Error("expected", nil, "got", err) 223 } 224 } 225 226 func TestTransactionQueue(t *testing.T) { 227 t.Parallel() 228 229 pool, key := setupTxPool() 230 defer pool.Stop() 231 232 tx := transaction(0, 100, key) 233 from, _ := deriveSender(tx) 234 pool.currentState.AddBalance(from, big.NewInt(1000)) 235 pool.lockedReset(nil, nil) 236 pool.enqueueTx(tx.Hash(), tx) 237 238 pool.promoteExecutables([]common.Address{from}) 239 if len(pool.pending) != 1 { 240 t.Error("expected valid txs to be 1 is", len(pool.pending)) 241 } 242 243 tx = transaction(1, 100, key) 244 from, _ = deriveSender(tx) 245 pool.currentState.SetNonce(from, 2) 246 pool.enqueueTx(tx.Hash(), tx) 247 pool.promoteExecutables([]common.Address{from}) 248 if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok { 249 t.Error("expected transaction to be in tx pool") 250 } 251 252 if len(pool.queue) > 0 { 253 t.Error("expected transaction queue to be empty. is", len(pool.queue)) 254 } 255 256 pool, key = setupTxPool() 257 defer pool.Stop() 258 259 tx1 := transaction(0, 100, key) 260 tx2 := transaction(10, 100, key) 261 tx3 := transaction(11, 100, key) 262 from, _ = deriveSender(tx1) 263 pool.currentState.AddBalance(from, big.NewInt(1000)) 264 pool.lockedReset(nil, nil) 265 266 pool.enqueueTx(tx1.Hash(), tx1) 267 pool.enqueueTx(tx2.Hash(), tx2) 268 pool.enqueueTx(tx3.Hash(), tx3) 269 270 pool.promoteExecutables([]common.Address{from}) 271 272 if len(pool.pending) != 1 { 273 t.Error("expected tx pool to be 1, got", len(pool.pending)) 274 } 275 if pool.queue[from].Len() != 2 { 276 t.Error("expected len(queue) == 2, got", pool.queue[from].Len()) 277 } 278 } 279 280 func TestTransactionNegativeValue(t *testing.T) { 281 t.Parallel() 282 283 pool, key := setupTxPool() 284 defer pool.Stop() 285 286 tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) 287 from, _ := deriveSender(tx) 288 pool.currentState.AddBalance(from, big.NewInt(1)) 289 if err := pool.AddRemote(tx); err != ErrNegativeValue { 290 t.Error("expected", ErrNegativeValue, "got", err) 291 } 292 } 293 294 func TestTransactionChainFork(t *testing.T) { 295 t.Parallel() 296 297 pool, key := setupTxPool() 298 defer pool.Stop() 299 300 addr := crypto.PubkeyToAddress(key.PublicKey) 301 resetState := func() { 302 db := rawdb.NewMemoryDatabase() 303 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 304 statedb.AddBalance(addr, big.NewInt(100000000000000)) 305 306 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 307 pool.lockedReset(nil, nil) 308 } 309 resetState() 310 311 tx := transaction(0, 100000, key) 312 if _, err := pool.add(tx, false); err != nil { 313 t.Error("didn't expect error", err) 314 } 315 pool.removeTx(tx.Hash()) 316 317 resetState() 318 if _, err := pool.add(tx, false); err != nil { 319 t.Error("didn't expect error", err) 320 } 321 } 322 323 func TestTransactionDoubleNonce(t *testing.T) { 324 t.Parallel() 325 326 pool, key := setupTxPool() 327 defer pool.Stop() 328 329 addr := crypto.PubkeyToAddress(key.PublicKey) 330 resetState := func() { 331 db := rawdb.NewMemoryDatabase() 332 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 333 statedb.AddBalance(addr, big.NewInt(100000000000000)) 334 335 pool.chain = &testBlockChain{statedb, 1000000, new(event.Feed)} 336 pool.lockedReset(nil, nil) 337 } 338 resetState() 339 340 signer := types.HomesteadSigner{} 341 tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(1), nil), signer, key) 342 tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(2), nil), signer, key) 343 tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key) 344 345 if replace, err := pool.add(tx1, false); err != nil || replace { 346 t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace) 347 } 348 if replace, err := pool.add(tx2, false); err != nil || !replace { 349 t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace) 350 } 351 pool.promoteExecutables([]common.Address{addr}) 352 if pool.pending[addr].Len() != 1 { 353 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 354 } 355 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 356 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 357 } 358 pool.add(tx3, false) 359 pool.promoteExecutables([]common.Address{addr}) 360 if pool.pending[addr].Len() != 1 { 361 t.Error("expected 1 pending transactions, got", pool.pending[addr].Len()) 362 } 363 if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() { 364 t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash()) 365 } 366 if len(pool.all) != 1 { 367 t.Error("expected 1 total transactions, got", len(pool.all)) 368 } 369 } 370 371 func TestTransactionMissingNonce(t *testing.T) { 372 t.Parallel() 373 374 pool, key := setupTxPool() 375 defer pool.Stop() 376 377 addr := crypto.PubkeyToAddress(key.PublicKey) 378 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 379 tx := transaction(1, 100000, key) 380 if _, err := pool.add(tx, false); err != nil { 381 t.Error("didn't expect error", err) 382 } 383 if len(pool.pending) != 0 { 384 t.Error("expected 0 pending transactions, got", len(pool.pending)) 385 } 386 if pool.queue[addr].Len() != 1 { 387 t.Error("expected 1 queued transaction, got", pool.queue[addr].Len()) 388 } 389 if len(pool.all) != 1 { 390 t.Error("expected 1 total transactions, got", len(pool.all)) 391 } 392 } 393 394 func TestTransactionNonceRecovery(t *testing.T) { 395 t.Parallel() 396 397 const n = 10 398 pool, key := setupTxPool() 399 defer pool.Stop() 400 401 addr := crypto.PubkeyToAddress(key.PublicKey) 402 pool.currentState.SetNonce(addr, n) 403 pool.currentState.AddBalance(addr, big.NewInt(100000000000000)) 404 pool.lockedReset(nil, nil) 405 406 tx := transaction(n, 100000, key) 407 if err := pool.AddRemote(tx); err != nil { 408 t.Error(err) 409 } 410 pool.currentState.SetNonce(addr, n-1) 411 pool.lockedReset(nil, nil) 412 if fn := pool.pendingState.GetNonce(addr); fn != n-1 { 413 t.Errorf("expected nonce to be %d, got %d", n-1, fn) 414 } 415 } 416 417 func TestTransactionDropping(t *testing.T) { 418 t.Parallel() 419 420 pool, key := setupTxPool() 421 defer pool.Stop() 422 423 account, _ := deriveSender(transaction(0, 0, key)) 424 pool.currentState.AddBalance(account, big.NewInt(1000)) 425 426 var ( 427 tx0 = transaction(0, 100, key) 428 tx1 = transaction(1, 200, key) 429 tx2 = transaction(2, 300, key) 430 tx10 = transaction(10, 100, key) 431 tx11 = transaction(11, 200, key) 432 tx12 = transaction(12, 300, key) 433 ) 434 pool.promoteTx(account, tx0.Hash(), tx0) 435 pool.promoteTx(account, tx1.Hash(), tx1) 436 pool.promoteTx(account, tx2.Hash(), tx2) 437 pool.enqueueTx(tx10.Hash(), tx10) 438 pool.enqueueTx(tx11.Hash(), tx11) 439 pool.enqueueTx(tx12.Hash(), tx12) 440 441 if pool.pending[account].Len() != 3 { 442 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 443 } 444 if pool.queue[account].Len() != 3 { 445 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 446 } 447 if len(pool.all) != 6 { 448 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 449 } 450 pool.lockedReset(nil, nil) 451 if pool.pending[account].Len() != 3 { 452 t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3) 453 } 454 if pool.queue[account].Len() != 3 { 455 t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3) 456 } 457 if len(pool.all) != 6 { 458 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6) 459 } 460 pool.currentState.AddBalance(account, big.NewInt(-650)) 461 pool.lockedReset(nil, nil) 462 463 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 464 t.Errorf("funded pending transaction missing: %v", tx0) 465 } 466 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok { 467 t.Errorf("funded pending transaction missing: %v", tx0) 468 } 469 if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok { 470 t.Errorf("out-of-fund pending transaction present: %v", tx1) 471 } 472 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 473 t.Errorf("funded queued transaction missing: %v", tx10) 474 } 475 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok { 476 t.Errorf("funded queued transaction missing: %v", tx10) 477 } 478 if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok { 479 t.Errorf("out-of-fund queued transaction present: %v", tx11) 480 } 481 if len(pool.all) != 4 { 482 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4) 483 } 484 pool.chain.(*testBlockChain).gasLimit = 100 485 pool.lockedReset(nil, nil) 486 487 if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok { 488 t.Errorf("funded pending transaction missing: %v", tx0) 489 } 490 if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok { 491 t.Errorf("over-gased pending transaction present: %v", tx1) 492 } 493 if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok { 494 t.Errorf("funded queued transaction missing: %v", tx10) 495 } 496 if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok { 497 t.Errorf("over-gased queued transaction present: %v", tx11) 498 } 499 if len(pool.all) != 2 { 500 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2) 501 } 502 } 503 504 func TestTransactionPostponing(t *testing.T) { 505 t.Parallel() 506 507 db := rawdb.NewMemoryDatabase() 508 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 509 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 510 511 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 512 defer pool.Stop() 513 514 keys := make([]*ecdsa.PrivateKey, 2) 515 accs := make([]common.Address, len(keys)) 516 517 for i := 0; i < len(keys); i++ { 518 keys[i], _ = crypto.GenerateKey() 519 accs[i] = crypto.PubkeyToAddress(keys[i].PublicKey) 520 521 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(50100)) 522 } 523 txs := []*types.Transaction{} 524 for i, key := range keys { 525 526 for j := 0; j < 100; j++ { 527 var tx *types.Transaction 528 if (i+j)%2 == 0 { 529 tx = transaction(uint64(j), 25000, key) 530 } else { 531 tx = transaction(uint64(j), 50000, key) 532 } 533 txs = append(txs, tx) 534 } 535 } 536 for i, err := range pool.AddRemotes(txs) { 537 if err != nil { 538 t.Fatalf("tx %d: failed to add transactions: %v", i, err) 539 } 540 } 541 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 542 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 543 } 544 if len(pool.queue) != 0 { 545 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 546 } 547 if len(pool.all) != len(txs) { 548 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) 549 } 550 pool.lockedReset(nil, nil) 551 if pending := pool.pending[accs[0]].Len() + pool.pending[accs[1]].Len(); pending != len(txs) { 552 t.Errorf("pending transaction mismatch: have %d, want %d", pending, len(txs)) 553 } 554 if len(pool.queue) != 0 { 555 t.Errorf("queued accounts mismatch: have %d, want %d", len(pool.queue), 0) 556 } 557 if len(pool.all) != len(txs) { 558 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)) 559 } 560 for _, addr := range accs { 561 pool.currentState.AddBalance(addr, big.NewInt(-1)) 562 } 563 pool.lockedReset(nil, nil) 564 565 if _, ok := pool.pending[accs[0]].txs.items[txs[0].Nonce()]; !ok { 566 t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txs[0]) 567 } 568 if _, ok := pool.queue[accs[0]].txs.items[txs[0].Nonce()]; ok { 569 t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txs[0]) 570 } 571 for i, tx := range txs[1:100] { 572 if i%2 == 1 { 573 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 574 t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx) 575 } 576 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; !ok { 577 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx) 578 } 579 } else { 580 if _, ok := pool.pending[accs[0]].txs.items[tx.Nonce()]; ok { 581 t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx) 582 } 583 if _, ok := pool.queue[accs[0]].txs.items[tx.Nonce()]; ok { 584 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx) 585 } 586 } 587 } 588 if pool.pending[accs[1]] != nil { 589 t.Errorf("invalidated account still has pending transactions") 590 } 591 for i, tx := range txs[100:] { 592 if i%2 == 1 { 593 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; !ok { 594 t.Errorf("tx %d: valid but future transaction missing from future queue: %v", 100+i, tx) 595 } 596 } else { 597 if _, ok := pool.queue[accs[1]].txs.items[tx.Nonce()]; ok { 598 t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", 100+i, tx) 599 } 600 } 601 } 602 if len(pool.all) != len(txs)/2 { 603 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txs)/2) 604 } 605 } 606 607 func TestTransactionGapFilling(t *testing.T) { 608 t.Parallel() 609 610 pool, key := setupTxPool() 611 defer pool.Stop() 612 613 account, _ := deriveSender(transaction(0, 0, key)) 614 pool.currentState.AddBalance(account, big.NewInt(1000000)) 615 616 events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5) 617 sub := pool.txFeed.Subscribe(events) 618 defer sub.Unsubscribe() 619 620 if err := pool.AddRemote(transaction(0, 100000, key)); err != nil { 621 t.Fatalf("failed to add pending transaction: %v", err) 622 } 623 if err := pool.AddRemote(transaction(2, 100000, key)); err != nil { 624 t.Fatalf("failed to add queued transaction: %v", err) 625 } 626 pending, queued := pool.Stats() 627 if pending != 1 { 628 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1) 629 } 630 if queued != 1 { 631 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 632 } 633 if err := validateEvents(events, 1); err != nil { 634 t.Fatalf("original event firing failed: %v", err) 635 } 636 if err := validateTxPoolInternals(pool); err != nil { 637 t.Fatalf("pool internal state corrupted: %v", err) 638 } 639 if err := pool.AddRemote(transaction(1, 100000, key)); err != nil { 640 t.Fatalf("failed to add gapped transaction: %v", err) 641 } 642 pending, queued = pool.Stats() 643 if pending != 3 { 644 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 645 } 646 if queued != 0 { 647 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 648 } 649 if err := validateEvents(events, 2); err != nil { 650 t.Fatalf("gap-filling event firing failed: %v", err) 651 } 652 if err := validateTxPoolInternals(pool); err != nil { 653 t.Fatalf("pool internal state corrupted: %v", err) 654 } 655 } 656 657 func TestTransactionQueueAccountLimiting(t *testing.T) { 658 t.Parallel() 659 660 pool, key := setupTxPool() 661 defer pool.Stop() 662 663 account, _ := deriveSender(transaction(0, 0, key)) 664 pool.currentState.AddBalance(account, big.NewInt(1000000)) 665 666 for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ { 667 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 668 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 669 } 670 if len(pool.pending) != 0 { 671 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0) 672 } 673 if i <= testTxPoolConfig.AccountQueue { 674 if pool.queue[account].Len() != int(i) { 675 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i) 676 } 677 } else { 678 if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) { 679 t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue) 680 } 681 } 682 } 683 if len(pool.all) != int(testTxPoolConfig.AccountQueue) { 684 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue) 685 } 686 } 687 688 func TestTransactionQueueGlobalLimiting(t *testing.T) { 689 testTransactionQueueGlobalLimiting(t, false) 690 } 691 func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { 692 testTransactionQueueGlobalLimiting(t, true) 693 } 694 695 func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { 696 t.Parallel() 697 698 db := rawdb.NewMemoryDatabase() 699 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 700 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 701 702 config := testTxPoolConfig 703 config.NoLocals = nolocals 704 config.GlobalQueue = config.AccountQueue*3 - 1 705 706 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 707 defer pool.Stop() 708 709 keys := make([]*ecdsa.PrivateKey, 5) 710 for i := 0; i < len(keys); i++ { 711 keys[i], _ = crypto.GenerateKey() 712 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 713 } 714 local := keys[len(keys)-1] 715 716 nonces := make(map[common.Address]uint64) 717 718 txs := make(types.Transactions, 0, 3*config.GlobalQueue) 719 for len(txs) < cap(txs) { 720 key := keys[rand.Intn(len(keys)-1)] 721 addr := crypto.PubkeyToAddress(key.PublicKey) 722 723 txs = append(txs, transaction(nonces[addr]+1, 100000, key)) 724 nonces[addr]++ 725 } 726 pool.AddRemotes(txs) 727 728 queued := 0 729 for addr, list := range pool.queue { 730 if list.Len() > int(config.AccountQueue) { 731 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 732 } 733 queued += list.Len() 734 } 735 if queued > int(config.GlobalQueue) { 736 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 737 } 738 txs = txs[:0] 739 for i := uint64(0); i < 3*config.GlobalQueue; i++ { 740 txs = append(txs, transaction(i+1, 100000, local)) 741 } 742 pool.AddLocals(txs) 743 744 if nolocals { 745 queued := 0 746 for addr, list := range pool.queue { 747 if list.Len() > int(config.AccountQueue) { 748 t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue) 749 } 750 queued += list.Len() 751 } 752 if queued > int(config.GlobalQueue) { 753 t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue) 754 } 755 } else { 756 if len(pool.queue) != 1 { 757 t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1) 758 } 759 if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue { 760 t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue) 761 } 762 } 763 } 764 765 func TestTransactionQueueTimeLimiting(t *testing.T) { testTransactionQueueTimeLimiting(t, false) } 766 func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { 767 testTransactionQueueTimeLimiting(t, true) 768 } 769 770 func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { 771 defer func(old time.Duration) { evictionInterval = old }(evictionInterval) 772 evictionInterval = time.Second 773 774 db := rawdb.NewMemoryDatabase() 775 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 776 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 777 778 config := testTxPoolConfig 779 config.Lifetime = time.Second 780 config.NoLocals = nolocals 781 782 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 783 defer pool.Stop() 784 785 local, _ := crypto.GenerateKey() 786 remote, _ := crypto.GenerateKey() 787 788 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 789 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 790 791 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 792 t.Fatalf("failed to add local transaction: %v", err) 793 } 794 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil { 795 t.Fatalf("failed to add remote transaction: %v", err) 796 } 797 pending, queued := pool.Stats() 798 if pending != 0 { 799 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 800 } 801 if queued != 2 { 802 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 803 } 804 if err := validateTxPoolInternals(pool); err != nil { 805 t.Fatalf("pool internal state corrupted: %v", err) 806 } 807 time.Sleep(2 * config.Lifetime) 808 809 pending, queued = pool.Stats() 810 if pending != 0 { 811 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 812 } 813 if nolocals { 814 if queued != 0 { 815 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 816 } 817 } else { 818 if queued != 1 { 819 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 820 } 821 } 822 if err := validateTxPoolInternals(pool); err != nil { 823 t.Fatalf("pool internal state corrupted: %v", err) 824 } 825 } 826 827 func TestTransactionPendingLimiting(t *testing.T) { 828 t.Parallel() 829 830 pool, key := setupTxPool() 831 defer pool.Stop() 832 833 account, _ := deriveSender(transaction(0, 0, key)) 834 pool.currentState.AddBalance(account, big.NewInt(1000000)) 835 836 events := make(chan TxPreEvent, testTxPoolConfig.AccountQueue+5) 837 sub := pool.txFeed.Subscribe(events) 838 defer sub.Unsubscribe() 839 840 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 841 if err := pool.AddRemote(transaction(i, 100000, key)); err != nil { 842 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 843 } 844 if pool.pending[account].Len() != int(i)+1 { 845 t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1) 846 } 847 if len(pool.queue) != 0 { 848 t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0) 849 } 850 } 851 if len(pool.all) != int(testTxPoolConfig.AccountQueue+5) { 852 t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5) 853 } 854 if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { 855 t.Fatalf("event firing failed: %v", err) 856 } 857 if err := validateTxPoolInternals(pool); err != nil { 858 t.Fatalf("pool internal state corrupted: %v", err) 859 } 860 } 861 862 func TestTransactionQueueLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 1) } 863 func TestTransactionPendingLimitingEquivalency(t *testing.T) { 864 testTransactionLimitingEquivalency(t, 0) 865 } 866 867 func testTransactionLimitingEquivalency(t *testing.T, origin uint64) { 868 t.Parallel() 869 870 pool1, key1 := setupTxPool() 871 defer pool1.Stop() 872 873 account1, _ := deriveSender(transaction(0, 0, key1)) 874 pool1.currentState.AddBalance(account1, big.NewInt(1000000)) 875 876 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 877 if err := pool1.AddRemote(transaction(origin+i, 100000, key1)); err != nil { 878 t.Fatalf("tx %d: failed to add transaction: %v", i, err) 879 } 880 } 881 pool2, key2 := setupTxPool() 882 defer pool2.Stop() 883 884 account2, _ := deriveSender(transaction(0, 0, key2)) 885 pool2.currentState.AddBalance(account2, big.NewInt(1000000)) 886 887 txs := []*types.Transaction{} 888 for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ { 889 txs = append(txs, transaction(origin+i, 100000, key2)) 890 } 891 pool2.AddRemotes(txs) 892 893 if len(pool1.pending) != len(pool2.pending) { 894 t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending)) 895 } 896 if len(pool1.queue) != len(pool2.queue) { 897 t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue)) 898 } 899 if len(pool1.all) != len(pool2.all) { 900 t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all)) 901 } 902 if err := validateTxPoolInternals(pool1); err != nil { 903 t.Errorf("pool 1 internal state corrupted: %v", err) 904 } 905 if err := validateTxPoolInternals(pool2); err != nil { 906 t.Errorf("pool 2 internal state corrupted: %v", err) 907 } 908 } 909 910 func TestTransactionPendingGlobalLimiting(t *testing.T) { 911 t.Parallel() 912 913 db := rawdb.NewMemoryDatabase() 914 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 915 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 916 917 config := testTxPoolConfig 918 config.GlobalSlots = config.AccountSlots * 10 919 920 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 921 defer pool.Stop() 922 923 keys := make([]*ecdsa.PrivateKey, 5) 924 for i := 0; i < len(keys); i++ { 925 keys[i], _ = crypto.GenerateKey() 926 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 927 } 928 nonces := make(map[common.Address]uint64) 929 930 txs := types.Transactions{} 931 for _, key := range keys { 932 addr := crypto.PubkeyToAddress(key.PublicKey) 933 for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ { 934 txs = append(txs, transaction(nonces[addr], 100000, key)) 935 nonces[addr]++ 936 } 937 } 938 pool.AddRemotes(txs) 939 940 pending := 0 941 for _, list := range pool.pending { 942 pending += list.Len() 943 } 944 if pending > int(config.GlobalSlots) { 945 t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) 946 } 947 if err := validateTxPoolInternals(pool); err != nil { 948 t.Fatalf("pool internal state corrupted: %v", err) 949 } 950 } 951 952 func TestTransactionCapClearsFromAll(t *testing.T) { 953 t.Parallel() 954 955 db := rawdb.NewMemoryDatabase() 956 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 957 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 958 959 config := testTxPoolConfig 960 config.AccountSlots = 2 961 config.AccountQueue = 2 962 config.GlobalSlots = 8 963 964 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 965 defer pool.Stop() 966 967 key, _ := crypto.GenerateKey() 968 addr := crypto.PubkeyToAddress(key.PublicKey) 969 pool.currentState.AddBalance(addr, big.NewInt(1000000)) 970 971 txs := types.Transactions{} 972 for j := 0; j < int(config.GlobalSlots)*2; j++ { 973 txs = append(txs, transaction(uint64(j), 100000, key)) 974 } 975 pool.AddRemotes(txs) 976 if err := validateTxPoolInternals(pool); err != nil { 977 t.Fatalf("pool internal state corrupted: %v", err) 978 } 979 } 980 981 func TestTransactionPendingMinimumAllowance(t *testing.T) { 982 t.Parallel() 983 984 db := rawdb.NewMemoryDatabase() 985 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 986 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 987 988 config := testTxPoolConfig 989 config.GlobalSlots = 0 990 991 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 992 defer pool.Stop() 993 994 keys := make([]*ecdsa.PrivateKey, 5) 995 for i := 0; i < len(keys); i++ { 996 keys[i], _ = crypto.GenerateKey() 997 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 998 } 999 nonces := make(map[common.Address]uint64) 1000 1001 txs := types.Transactions{} 1002 for _, key := range keys { 1003 addr := crypto.PubkeyToAddress(key.PublicKey) 1004 for j := 0; j < int(config.AccountSlots)*2; j++ { 1005 txs = append(txs, transaction(nonces[addr], 100000, key)) 1006 nonces[addr]++ 1007 } 1008 } 1009 pool.AddRemotes(txs) 1010 1011 for addr, list := range pool.pending { 1012 if list.Len() != int(config.AccountSlots) { 1013 t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) 1014 } 1015 } 1016 if err := validateTxPoolInternals(pool); err != nil { 1017 t.Fatalf("pool internal state corrupted: %v", err) 1018 } 1019 } 1020 1021 func TestTransactionPoolRepricing(t *testing.T) { 1022 t.Parallel() 1023 1024 db := rawdb.NewMemoryDatabase() 1025 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1026 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1027 1028 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 1029 defer pool.Stop() 1030 1031 events := make(chan TxPreEvent, 32) 1032 sub := pool.txFeed.Subscribe(events) 1033 defer sub.Unsubscribe() 1034 1035 keys := make([]*ecdsa.PrivateKey, 4) 1036 for i := 0; i < len(keys); i++ { 1037 keys[i], _ = crypto.GenerateKey() 1038 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1039 } 1040 txs := types.Transactions{} 1041 1042 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(2), keys[0])) 1043 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[0])) 1044 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[0])) 1045 1046 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) 1047 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[1])) 1048 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(2), keys[1])) 1049 1050 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[2])) 1051 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) 1052 txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2])) 1053 1054 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3]) 1055 1056 pool.AddRemotes(txs) 1057 pool.AddLocal(ltx) 1058 1059 pending, queued := pool.Stats() 1060 if pending != 7 { 1061 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7) 1062 } 1063 if queued != 3 { 1064 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) 1065 } 1066 if err := validateEvents(events, 7); err != nil { 1067 t.Fatalf("original event firing failed: %v", err) 1068 } 1069 if err := validateTxPoolInternals(pool); err != nil { 1070 t.Fatalf("pool internal state corrupted: %v", err) 1071 } 1072 pool.SetGasPrice(big.NewInt(2)) 1073 1074 pending, queued = pool.Stats() 1075 if pending != 2 { 1076 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1077 } 1078 if queued != 5 { 1079 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5) 1080 } 1081 if err := validateEvents(events, 0); err != nil { 1082 t.Fatalf("reprice event firing failed: %v", err) 1083 } 1084 if err := validateTxPoolInternals(pool); err != nil { 1085 t.Fatalf("pool internal state corrupted: %v", err) 1086 } 1087 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(1), keys[0])); err != ErrUnderpriced { 1088 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1089 } 1090 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1091 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1092 } 1093 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), keys[2])); err != ErrUnderpriced { 1094 t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1095 } 1096 if err := validateEvents(events, 0); err != nil { 1097 t.Fatalf("post-reprice event firing failed: %v", err) 1098 } 1099 if err := validateTxPoolInternals(pool); err != nil { 1100 t.Fatalf("pool internal state corrupted: %v", err) 1101 } 1102 tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3]) 1103 if err := pool.AddLocal(tx); err != nil { 1104 t.Fatalf("failed to add underpriced local transaction: %v", err) 1105 } 1106 if pending, _ = pool.Stats(); pending != 3 { 1107 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1108 } 1109 if err := validateEvents(events, 1); err != nil { 1110 t.Fatalf("post-reprice local event firing failed: %v", err) 1111 } 1112 if err := validateTxPoolInternals(pool); err != nil { 1113 t.Fatalf("pool internal state corrupted: %v", err) 1114 } 1115 if err := pool.AddRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil { 1116 t.Fatalf("failed to add pending transaction: %v", err) 1117 } 1118 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), keys[1])); err != nil { 1119 t.Fatalf("failed to add pending transaction: %v", err) 1120 } 1121 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), keys[2])); err != nil { 1122 t.Fatalf("failed to add queued transaction: %v", err) 1123 } 1124 if err := validateEvents(events, 5); err != nil { 1125 t.Fatalf("post-reprice event firing failed: %v", err) 1126 } 1127 if err := validateTxPoolInternals(pool); err != nil { 1128 t.Fatalf("pool internal state corrupted: %v", err) 1129 } 1130 } 1131 1132 func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { 1133 t.Parallel() 1134 1135 db := rawdb.NewMemoryDatabase() 1136 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1137 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1138 1139 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 1140 defer pool.Stop() 1141 1142 keys := make([]*ecdsa.PrivateKey, 3) 1143 for i := 0; i < len(keys); i++ { 1144 keys[i], _ = crypto.GenerateKey() 1145 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000*1000000)) 1146 } 1147 for i := uint64(0); i < 500; i++ { 1148 p_tx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2]) 1149 if err := pool.AddLocal(p_tx); err != nil { 1150 t.Fatal(err) 1151 } 1152 q_tx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2]) 1153 if err := pool.AddLocal(q_tx); err != nil { 1154 t.Fatal(err) 1155 } 1156 } 1157 pending, queued := pool.Stats() 1158 expPending, expQueued := 500, 500 1159 validate := func() { 1160 pending, queued = pool.Stats() 1161 if pending != expPending { 1162 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending) 1163 } 1164 if queued != expQueued { 1165 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) 1166 } 1167 1168 if err := validateTxPoolInternals(pool); err != nil { 1169 t.Fatalf("pool internal state corrupted: %v", err) 1170 } 1171 } 1172 validate() 1173 1174 pool.SetGasPrice(big.NewInt(2)) 1175 validate() 1176 1177 pool.SetGasPrice(big.NewInt(2)) 1178 pool.SetGasPrice(big.NewInt(4)) 1179 pool.SetGasPrice(big.NewInt(8)) 1180 pool.SetGasPrice(big.NewInt(100)) 1181 validate() 1182 } 1183 1184 func TestTransactionPoolUnderpricing(t *testing.T) { 1185 t.Parallel() 1186 1187 db := rawdb.NewMemoryDatabase() 1188 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1189 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1190 1191 config := testTxPoolConfig 1192 config.GlobalSlots = 2 1193 config.GlobalQueue = 2 1194 1195 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 1196 defer pool.Stop() 1197 1198 events := make(chan TxPreEvent, 32) 1199 sub := pool.txFeed.Subscribe(events) 1200 defer sub.Unsubscribe() 1201 1202 keys := make([]*ecdsa.PrivateKey, 3) 1203 for i := 0; i < len(keys); i++ { 1204 keys[i], _ = crypto.GenerateKey() 1205 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1206 } 1207 txs := types.Transactions{} 1208 1209 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) 1210 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) 1211 1212 txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) 1213 1214 ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2]) 1215 1216 pool.AddRemotes(txs) 1217 pool.AddLocal(ltx) 1218 1219 pending, queued := pool.Stats() 1220 if pending != 3 { 1221 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3) 1222 } 1223 if queued != 1 { 1224 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1225 } 1226 if err := validateEvents(events, 3); err != nil { 1227 t.Fatalf("original event firing failed: %v", err) 1228 } 1229 if err := validateTxPoolInternals(pool); err != nil { 1230 t.Fatalf("pool internal state corrupted: %v", err) 1231 } 1232 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), keys[1])); err != ErrUnderpriced { 1233 t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced) 1234 } 1235 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(3), keys[1])); err != nil { 1236 t.Fatalf("failed to add well priced transaction: %v", err) 1237 } 1238 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil { 1239 t.Fatalf("failed to add well priced transaction: %v", err) 1240 } 1241 if err := pool.AddRemote(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil { 1242 t.Fatalf("failed to add well priced transaction: %v", err) 1243 } 1244 pending, queued = pool.Stats() 1245 if pending != 2 { 1246 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1247 } 1248 if queued != 2 { 1249 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1250 } 1251 if err := validateEvents(events, 2); err != nil { 1252 t.Fatalf("additional event firing failed: %v", err) 1253 } 1254 if err := validateTxPoolInternals(pool); err != nil { 1255 t.Fatalf("pool internal state corrupted: %v", err) 1256 } 1257 tx := pricedTransaction(1, 100000, big.NewInt(0), keys[2]) 1258 if err := pool.AddLocal(tx); err != nil { 1259 t.Fatalf("failed to add underpriced local transaction: %v", err) 1260 } 1261 pending, queued = pool.Stats() 1262 if pending != 2 { 1263 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1264 } 1265 if queued != 2 { 1266 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1267 } 1268 if err := validateEvents(events, 1); err != nil { 1269 t.Fatalf("local event firing failed: %v", err) 1270 } 1271 if err := validateTxPoolInternals(pool); err != nil { 1272 t.Fatalf("pool internal state corrupted: %v", err) 1273 } 1274 } 1275 1276 func TestTransactionReplacement(t *testing.T) { 1277 t.Parallel() 1278 1279 db := rawdb.NewMemoryDatabase() 1280 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1281 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1282 1283 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 1284 defer pool.Stop() 1285 1286 events := make(chan TxPreEvent, 32) 1287 sub := pool.txFeed.Subscribe(events) 1288 defer sub.Unsubscribe() 1289 1290 key, _ := crypto.GenerateKey() 1291 pool.currentState.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) 1292 1293 price := int64(100) 1294 threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100 1295 1296 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), key)); err != nil { 1297 t.Fatalf("failed to add original cheap pending transaction: %v", err) 1298 } 1299 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1300 t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1301 } 1302 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(2), key)); err != nil { 1303 t.Fatalf("failed to replace original cheap pending transaction: %v", err) 1304 } 1305 if err := validateEvents(events, 2); err != nil { 1306 t.Fatalf("cheap replacement event firing failed: %v", err) 1307 } 1308 1309 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(price), key)); err != nil { 1310 t.Fatalf("failed to add original proper pending transaction: %v", err) 1311 } 1312 if err := pool.AddRemote(pricedTransaction(0, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1313 t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1314 } 1315 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(threshold), key)); err != nil { 1316 t.Fatalf("failed to replace original proper pending transaction: %v", err) 1317 } 1318 if err := validateEvents(events, 2); err != nil { 1319 t.Fatalf("proper replacement event firing failed: %v", err) 1320 } 1321 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(1), key)); err != nil { 1322 t.Fatalf("failed to add original cheap queued transaction: %v", err) 1323 } 1324 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(1), key)); err != ErrReplaceUnderpriced { 1325 t.Fatalf("original cheap queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1326 } 1327 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(2), key)); err != nil { 1328 t.Fatalf("failed to replace original cheap queued transaction: %v", err) 1329 } 1330 1331 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(price), key)); err != nil { 1332 t.Fatalf("failed to add original proper queued transaction: %v", err) 1333 } 1334 if err := pool.AddRemote(pricedTransaction(2, 100001, big.NewInt(threshold-1), key)); err != ErrReplaceUnderpriced { 1335 t.Fatalf("original proper queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced) 1336 } 1337 if err := pool.AddRemote(pricedTransaction(2, 100000, big.NewInt(threshold), key)); err != nil { 1338 t.Fatalf("failed to replace original proper queued transaction: %v", err) 1339 } 1340 1341 if err := validateEvents(events, 0); err != nil { 1342 t.Fatalf("queued replacement event firing failed: %v", err) 1343 } 1344 if err := validateTxPoolInternals(pool); err != nil { 1345 t.Fatalf("pool internal state corrupted: %v", err) 1346 } 1347 } 1348 1349 func TestTransactionJournaling(t *testing.T) { testTransactionJournaling(t, false) } 1350 func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) } 1351 1352 func testTransactionJournaling(t *testing.T, nolocals bool) { 1353 t.Parallel() 1354 1355 file, err := ioutil.TempFile("", "") 1356 if err != nil { 1357 t.Fatalf("failed to create temporary journal: %v", err) 1358 } 1359 journal := file.Name() 1360 defer os.Remove(journal) 1361 1362 file.Close() 1363 os.Remove(journal) 1364 1365 db := rawdb.NewMemoryDatabase() 1366 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1367 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1368 1369 config := testTxPoolConfig 1370 config.NoLocals = nolocals 1371 config.Journal = journal 1372 config.Rejournal = time.Second 1373 1374 pool := NewTxPool(config, params.TestChainConfig, blockchain, nil) 1375 1376 local, _ := crypto.GenerateKey() 1377 remote, _ := crypto.GenerateKey() 1378 1379 pool.currentState.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000)) 1380 pool.currentState.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000)) 1381 1382 if err := pool.AddLocal(pricedTransaction(0, 100000, big.NewInt(1), local)); err != nil { 1383 t.Fatalf("failed to add local transaction: %v", err) 1384 } 1385 if err := pool.AddLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil { 1386 t.Fatalf("failed to add local transaction: %v", err) 1387 } 1388 if err := pool.AddLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil { 1389 t.Fatalf("failed to add local transaction: %v", err) 1390 } 1391 if err := pool.AddRemote(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil { 1392 t.Fatalf("failed to add remote transaction: %v", err) 1393 } 1394 pending, queued := pool.Stats() 1395 if pending != 4 { 1396 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4) 1397 } 1398 if queued != 0 { 1399 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1400 } 1401 if err := validateTxPoolInternals(pool); err != nil { 1402 t.Fatalf("pool internal state corrupted: %v", err) 1403 } 1404 pool.Stop() 1405 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1406 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1407 1408 pool = NewTxPool(config, params.TestChainConfig, blockchain, nil) 1409 1410 pending, queued = pool.Stats() 1411 if queued != 0 { 1412 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1413 } 1414 if nolocals { 1415 if pending != 0 { 1416 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1417 } 1418 } else { 1419 if pending != 2 { 1420 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1421 } 1422 } 1423 if err := validateTxPoolInternals(pool); err != nil { 1424 t.Fatalf("pool internal state corrupted: %v", err) 1425 } 1426 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2) 1427 pool.lockedReset(nil, nil) 1428 time.Sleep(2 * config.Rejournal) 1429 pool.Stop() 1430 1431 statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1) 1432 blockchain = &testBlockChain{statedb, 1000000, new(event.Feed)} 1433 pool = NewTxPool(config, params.TestChainConfig, blockchain, nil) 1434 1435 pending, queued = pool.Stats() 1436 if pending != 0 { 1437 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0) 1438 } 1439 if nolocals { 1440 if queued != 0 { 1441 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) 1442 } 1443 } else { 1444 if queued != 1 { 1445 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) 1446 } 1447 } 1448 if err := validateTxPoolInternals(pool); err != nil { 1449 t.Fatalf("pool internal state corrupted: %v", err) 1450 } 1451 pool.Stop() 1452 } 1453 1454 func TestTransactionStatusCheck(t *testing.T) { 1455 t.Parallel() 1456 1457 db := rawdb.NewMemoryDatabase() 1458 statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) 1459 blockchain := &testBlockChain{statedb, 1000000, new(event.Feed)} 1460 1461 pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain, nil) 1462 defer pool.Stop() 1463 1464 keys := make([]*ecdsa.PrivateKey, 3) 1465 for i := 0; i < len(keys); i++ { 1466 keys[i], _ = crypto.GenerateKey() 1467 pool.currentState.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) 1468 } 1469 txs := types.Transactions{} 1470 1471 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) 1472 txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[1])) 1473 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[1])) 1474 txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2])) 1475 1476 pool.AddRemotes(txs) 1477 1478 pending, queued := pool.Stats() 1479 if pending != 2 { 1480 t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) 1481 } 1482 if queued != 2 { 1483 t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) 1484 } 1485 if err := validateTxPoolInternals(pool); err != nil { 1486 t.Fatalf("pool internal state corrupted: %v", err) 1487 } 1488 hashes := make([]common.Hash, len(txs)) 1489 for i, tx := range txs { 1490 hashes[i] = tx.Hash() 1491 } 1492 hashes = append(hashes, common.Hash{}) 1493 1494 statuses := pool.Status(hashes) 1495 expect := []TxStatus{TxStatusPending, TxStatusPending, TxStatusQueued, TxStatusQueued, TxStatusUnknown} 1496 1497 for i := 0; i < len(statuses); i++ { 1498 if statuses[i] != expect[i] { 1499 t.Errorf("transaction %d: status mismatch: have %v, want %v", i, statuses[i], expect[i]) 1500 } 1501 } 1502 } 1503 1504 func BenchmarkPendingDemotion100(b *testing.B) { benchmarkPendingDemotion(b, 100) } 1505 func BenchmarkPendingDemotion1000(b *testing.B) { benchmarkPendingDemotion(b, 1000) } 1506 func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) } 1507 1508 func benchmarkPendingDemotion(b *testing.B, size int) { 1509 pool, key := setupTxPool() 1510 defer pool.Stop() 1511 1512 account, _ := deriveSender(transaction(0, 0, key)) 1513 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1514 1515 for i := 0; i < size; i++ { 1516 tx := transaction(uint64(i), 100000, key) 1517 pool.promoteTx(account, tx.Hash(), tx) 1518 } 1519 b.ResetTimer() 1520 for i := 0; i < b.N; i++ { 1521 pool.demoteUnexecutables() 1522 } 1523 } 1524 1525 func BenchmarkFuturePromotion100(b *testing.B) { benchmarkFuturePromotion(b, 100) } 1526 func BenchmarkFuturePromotion1000(b *testing.B) { benchmarkFuturePromotion(b, 1000) } 1527 func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) } 1528 1529 func benchmarkFuturePromotion(b *testing.B, size int) { 1530 pool, key := setupTxPool() 1531 defer pool.Stop() 1532 1533 account, _ := deriveSender(transaction(0, 0, key)) 1534 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1535 1536 for i := 0; i < size; i++ { 1537 tx := transaction(uint64(1+i), 100000, key) 1538 pool.enqueueTx(tx.Hash(), tx) 1539 } 1540 b.ResetTimer() 1541 for i := 0; i < b.N; i++ { 1542 pool.promoteExecutables(nil) 1543 } 1544 } 1545 1546 func BenchmarkPoolInsert(b *testing.B) { 1547 pool, key := setupTxPool() 1548 defer pool.Stop() 1549 1550 account, _ := deriveSender(transaction(0, 0, key)) 1551 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1552 1553 txs := make(types.Transactions, b.N) 1554 for i := 0; i < b.N; i++ { 1555 txs[i] = transaction(uint64(i), 100000, key) 1556 } 1557 b.ResetTimer() 1558 for _, tx := range txs { 1559 pool.AddRemote(tx) 1560 } 1561 } 1562 1563 func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100) } 1564 func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000) } 1565 func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) } 1566 1567 func benchmarkPoolBatchInsert(b *testing.B, size int) { 1568 pool, key := setupTxPool() 1569 defer pool.Stop() 1570 1571 account, _ := deriveSender(transaction(0, 0, key)) 1572 pool.currentState.AddBalance(account, big.NewInt(1000000)) 1573 1574 batches := make([]types.Transactions, b.N) 1575 for i := 0; i < b.N; i++ { 1576 batches[i] = make(types.Transactions, size) 1577 for j := 0; j < size; j++ { 1578 batches[i][j] = transaction(uint64(size*i+j), 100000, key) 1579 } 1580 } 1581 b.ResetTimer() 1582 for _, batch := range batches { 1583 pool.AddRemotes(batch) 1584 } 1585 }