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