tx_pool_test.go 55.1 KB
Newer Older
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 6 7 8
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
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 13 14
// GNU Lesser General Public License for more details.
//
// 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 18 19 20
package core

import (
	"crypto/ecdsa"
21
	"fmt"
22
	"io/ioutil"
23
	"math/big"
24
	"math/rand"
25
	"os"
26
	"testing"
27
	"time"
28

Felix Lange's avatar
Felix Lange committed
29
	"github.com/ethereum/go-ethereum/common"
30
	"github.com/ethereum/go-ethereum/core/state"
31 32
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
33
	"github.com/ethereum/go-ethereum/ethdb"
34
	"github.com/ethereum/go-ethereum/event"
35
	"github.com/ethereum/go-ethereum/params"
36 37
)

38 39 40 41 42 43 44 45 46
// testTxPoolConfig is a transaction pool configuration without stateful disk
// sideeffects used during testing.
var testTxPoolConfig TxPoolConfig

func init() {
	testTxPoolConfig = DefaultTxPoolConfig
	testTxPoolConfig.Journal = ""
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
type testBlockChain struct {
	statedb       *state.StateDB
	gasLimit      *big.Int
	chainHeadFeed *event.Feed
	rmTxFeed      *event.Feed
}

func (bc *testBlockChain) State() (*state.StateDB, error) {
	return bc.statedb, nil
}

func (bc *testBlockChain) GasLimit() *big.Int {
	return new(big.Int).Set(bc.gasLimit)
}

func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription {
	return bc.chainHeadFeed.Subscribe(ch)
}

func (bc *testBlockChain) SubscribeRemovedTxEvent(ch chan<- RemovedTransactionEvent) event.Subscription {
	return bc.rmTxFeed.Subscribe(ch)
}

70
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
71 72 73 74 75
	return pricedTransaction(nonce, gaslimit, big.NewInt(1), key)
}

func pricedTransaction(nonce uint64, gaslimit, gasprice *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
	tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
76
	return tx
77 78
}

obscuren's avatar
obscuren committed
79 80
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
	db, _ := ethdb.NewMemDatabase()
81
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
82
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
obscuren's avatar
obscuren committed
83

84
	key, _ := crypto.GenerateKey()
85
	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
86

87
	return pool, key
88 89
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
// validateTxPoolInternals checks various consistency invariants within the pool.
func validateTxPoolInternals(pool *TxPool) error {
	pool.mu.RLock()
	defer pool.mu.RUnlock()

	// Ensure the total transaction set is consistent with pending + queued
	pending, queued := pool.stats()
	if total := len(pool.all); total != pending+queued {
		return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued)
	}
	if priced := pool.priced.items.Len() - pool.priced.stales; priced != pending+queued {
		return fmt.Errorf("total priced transaction count %d != %d pending + %d queued", priced, pending, queued)
	}
	// Ensure the next nonce to assign is the correct one
	for addr, txs := range pool.pending {
		// Find the last transaction
		var last uint64
		for nonce, _ := range txs.txs.items {
			if last < nonce {
				last = nonce
			}
		}
		if nonce := pool.pendingState.GetNonce(addr); nonce != last+1 {
			return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1)
		}
	}
	return nil
}

119 120 121 122
func deriveSender(tx *types.Transaction) (common.Address, error) {
	return types.Sender(types.HomesteadSigner{}, tx)
}

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
type testChain struct {
	*testBlockChain
	address common.Address
	trigger *bool
}

// testChain.State() is used multiple times to reset the pending state.
// when simulate is true it will create a state that indicates
// that tx0 and tx1 are included in the chain.
func (c *testChain) State() (*state.StateDB, error) {
	// delay "state change" by one. The tx pool fetches the
	// state multiple times and by delaying it a bit we simulate
	// a state change between those fetches.
	stdb := c.statedb
	if *c.trigger {
		db, _ := ethdb.NewMemDatabase()
		c.statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
		// simulate that the new head block included tx0 and tx1
		c.statedb.SetNonce(c.address, 2)
		c.statedb.SetBalance(c.address, new(big.Int).SetUint64(params.Ether))
		*c.trigger = false
	}
	return stdb, nil
}

148 149 150 151 152 153 154 155
// This test simulates a scenario where a new block is imported during a
// state reset and tests whether the pending state is in sync with the
// block head event that initiated the resetState().
func TestStateChangeDuringPoolReset(t *testing.T) {
	var (
		db, _      = ethdb.NewMemDatabase()
		key, _     = crypto.GenerateKey()
		address    = crypto.PubkeyToAddress(key.PublicKey)
156
		statedb, _ = state.New(common.Hash{}, state.NewDatabase(db))
157 158 159 160
		trigger    = false
	)

	// setup pool with 2 transaction in it
161
	statedb.SetBalance(address, new(big.Int).SetUint64(params.Ether))
162
	blockchain := &testChain{&testBlockChain{statedb, big.NewInt(1000000000), new(event.Feed), new(event.Feed)}, address, &trigger}
163 164 165 166

	tx0 := transaction(0, big.NewInt(100000), key)
	tx1 := transaction(1, big.NewInt(100000), key)

167
	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
168
	defer pool.Stop()
169

170
	nonce := pool.State().GetNonce(address)
171 172 173 174
	if nonce != 0 {
		t.Fatalf("Invalid nonce, want 0, got %d", nonce)
	}

175
	pool.AddRemotes(types.Transactions{tx0, tx1})
176

177
	nonce = pool.State().GetNonce(address)
178 179 180 181 182 183 184
	if nonce != 2 {
		t.Fatalf("Invalid nonce, want 2, got %d", nonce)
	}

	// trigger state change in the background
	trigger = true

185
	pool.lockedReset()
186

187
	pendingTx, err := pool.Pending()
188 189 190 191 192 193 194 195
	if err != nil {
		t.Fatalf("Could not fetch pending transactions: %v", err)
	}

	for addr, txs := range pendingTx {
		t.Logf("%0x: %d\n", addr, len(txs))
	}

196
	nonce = pool.State().GetNonce(address)
197 198 199 200 201
	if nonce != 2 {
		t.Fatalf("Invalid nonce, want 2, got %d", nonce)
	}
}

obscuren's avatar
obscuren committed
202 203
func TestInvalidTransactions(t *testing.T) {
	pool, key := setupTxPool()
204
	defer pool.Stop()
205

206
	tx := transaction(0, big.NewInt(100), key)
207
	from, _ := deriveSender(tx)
208
	currentState, _ := pool.blockChain.State()
209
	currentState.AddBalance(from, big.NewInt(1))
210
	if err := pool.AddRemote(tx); err != ErrInsufficientFunds {
obscuren's avatar
obscuren committed
211
		t.Error("expected", ErrInsufficientFunds)
212 213
	}

214
	balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(tx.Gas(), tx.GasPrice()))
215
	currentState.AddBalance(from, balance)
216
	if err := pool.AddRemote(tx); err != ErrIntrinsicGas {
217
		t.Error("expected", ErrIntrinsicGas, "got", err)
218
	}
219

220 221
	currentState.SetNonce(from, 1)
	currentState.AddBalance(from, big.NewInt(0xffffffffffffff))
222
	tx = transaction(0, big.NewInt(100000), key)
223
	if err := pool.AddRemote(tx); err != ErrNonceTooLow {
224
		t.Error("expected", ErrNonceTooLow)
225
	}
226 227

	tx = transaction(1, big.NewInt(100000), key)
228
	pool.gasPrice = big.NewInt(1000)
229
	if err := pool.AddRemote(tx); err != ErrUnderpriced {
230
		t.Error("expected", ErrUnderpriced, "got", err)
231
	}
232
	if err := pool.AddLocal(tx); err != nil {
233 234
		t.Error("expected", nil, "got", err)
	}
235 236 237 238
}

func TestTransactionQueue(t *testing.T) {
	pool, key := setupTxPool()
239 240
	defer pool.Stop()

241
	tx := transaction(0, big.NewInt(100), key)
242
	from, _ := deriveSender(tx)
243
	currentState, _ := pool.blockChain.State()
244
	currentState.AddBalance(from, big.NewInt(1000))
245
	pool.lockedReset()
246
	pool.enqueueTx(tx.Hash(), tx)
247

248
	pool.promoteExecutables(currentState, []common.Address{from})
249 250
	if len(pool.pending) != 1 {
		t.Error("expected valid txs to be 1 is", len(pool.pending))
251 252
	}

253
	tx = transaction(1, big.NewInt(100), key)
254
	from, _ = deriveSender(tx)
255
	currentState.SetNonce(from, 2)
256
	pool.enqueueTx(tx.Hash(), tx)
257
	pool.promoteExecutables(currentState, []common.Address{from})
258
	if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
259 260 261
		t.Error("expected transaction to be in tx pool")
	}

262 263
	if len(pool.queue) > 0 {
		t.Error("expected transaction queue to be empty. is", len(pool.queue))
264 265 266
	}

	pool, key = setupTxPool()
267 268
	defer pool.Stop()

269 270 271
	tx1 := transaction(0, big.NewInt(100), key)
	tx2 := transaction(10, big.NewInt(100), key)
	tx3 := transaction(11, big.NewInt(100), key)
272
	from, _ = deriveSender(tx1)
273
	currentState, _ = pool.blockChain.State()
274
	currentState.AddBalance(from, big.NewInt(1000))
275
	pool.lockedReset()
276

277 278 279
	pool.enqueueTx(tx1.Hash(), tx1)
	pool.enqueueTx(tx2.Hash(), tx2)
	pool.enqueueTx(tx3.Hash(), tx3)
280

281
	pool.promoteExecutables(currentState, []common.Address{from})
282

283
	if len(pool.pending) != 1 {
284
		t.Error("expected tx pool to be 1, got", len(pool.pending))
285
	}
286 287
	if pool.queue[from].Len() != 2 {
		t.Error("expected len(queue) == 2, got", pool.queue[from].Len())
288 289
	}
}
290 291 292

func TestRemoveTx(t *testing.T) {
	pool, key := setupTxPool()
293 294
	defer pool.Stop()

295
	addr := crypto.PubkeyToAddress(key.PublicKey)
296
	currentState, _ := pool.blockChain.State()
297 298 299 300 301 302 303
	currentState.AddBalance(addr, big.NewInt(1))

	tx1 := transaction(0, big.NewInt(100), key)
	tx2 := transaction(2, big.NewInt(100), key)

	pool.promoteTx(addr, tx1.Hash(), tx1)
	pool.enqueueTx(tx2.Hash(), tx2)
304

305 306 307
	if len(pool.queue) != 1 {
		t.Error("expected queue to be 1, got", len(pool.queue))
	}
308
	if len(pool.pending) != 1 {
309
		t.Error("expected pending to be 1, got", len(pool.pending))
310
	}
311 312 313
	pool.Remove(tx1.Hash())
	pool.Remove(tx2.Hash())

314 315 316
	if len(pool.queue) > 0 {
		t.Error("expected queue to be 0, got", len(pool.queue))
	}
317
	if len(pool.pending) > 0 {
318
		t.Error("expected pending to be 0, got", len(pool.pending))
319 320
	}
}
321 322 323

func TestNegativeValue(t *testing.T) {
	pool, key := setupTxPool()
324
	defer pool.Stop()
325

326
	tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key)
327
	from, _ := deriveSender(tx)
328
	currentState, _ := pool.blockChain.State()
329
	currentState.AddBalance(from, big.NewInt(1))
330
	if err := pool.AddRemote(tx); err != ErrNegativeValue {
331 332 333
		t.Error("expected", ErrNegativeValue, "got", err)
	}
}
334 335 336

func TestTransactionChainFork(t *testing.T) {
	pool, key := setupTxPool()
337 338
	defer pool.Stop()

339
	addr := crypto.PubkeyToAddress(key.PublicKey)
340 341
	resetState := func() {
		db, _ := ethdb.NewMemDatabase()
342
		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
343 344
		pool.blockChain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
		currentState, _ := pool.blockChain.State()
345
		currentState.AddBalance(addr, big.NewInt(100000000000000))
346
		pool.lockedReset()
347 348 349
	}
	resetState()

350
	tx := transaction(0, big.NewInt(100000), key)
351
	if _, err := pool.add(tx, false); err != nil {
352 353
		t.Error("didn't expect error", err)
	}
354
	pool.RemoveBatch([]*types.Transaction{tx})
355 356

	// reset the pool's internal state
357
	resetState()
358
	if _, err := pool.add(tx, false); err != nil {
359 360 361 362 363 364
		t.Error("didn't expect error", err)
	}
}

func TestTransactionDoubleNonce(t *testing.T) {
	pool, key := setupTxPool()
365 366
	defer pool.Stop()

367
	addr := crypto.PubkeyToAddress(key.PublicKey)
368 369
	resetState := func() {
		db, _ := ethdb.NewMemDatabase()
370
		statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
371 372
		pool.blockChain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
		currentState, _ := pool.blockChain.State()
373
		currentState.AddBalance(addr, big.NewInt(100000000000000))
374
		pool.lockedReset()
375 376 377
	}
	resetState()

378
	signer := types.HomesteadSigner{}
379 380 381
	tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key)
	tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key)
	tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key)
382 383

	// Add the first two transaction, ensure higher priced stays only
384
	if replace, err := pool.add(tx1, false); err != nil || replace {
385
		t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace)
386
	}
387
	if replace, err := pool.add(tx2, false); err != nil || !replace {
388
		t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
389
	}
390
	state, _ := pool.blockChain.State()
391
	pool.promoteExecutables(state, []common.Address{addr})
392 393
	if pool.pending[addr].Len() != 1 {
		t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
394
	}
395
	if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
396 397
		t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
	}
398
	// Add the third transaction and ensure it's not saved (smaller price)
399
	pool.add(tx3, false)
400
	pool.promoteExecutables(state, []common.Address{addr})
401 402
	if pool.pending[addr].Len() != 1 {
		t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
403
	}
404
	if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx2.Hash() {
405 406 407 408 409
		t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
	}
	// Ensure the total transaction count is correct
	if len(pool.all) != 1 {
		t.Error("expected 1 total transactions, got", len(pool.all))
410 411
	}
}
412 413 414

func TestMissingNonce(t *testing.T) {
	pool, key := setupTxPool()
415 416
	defer pool.Stop()

417
	addr := crypto.PubkeyToAddress(key.PublicKey)
418
	currentState, _ := pool.blockChain.State()
419
	currentState.AddBalance(addr, big.NewInt(100000000000000))
420
	tx := transaction(1, big.NewInt(100000), key)
421
	if _, err := pool.add(tx, false); err != nil {
422 423
		t.Error("didn't expect error", err)
	}
424 425
	if len(pool.pending) != 0 {
		t.Error("expected 0 pending transactions, got", len(pool.pending))
426
	}
427 428
	if pool.queue[addr].Len() != 1 {
		t.Error("expected 1 queued transaction, got", pool.queue[addr].Len())
429
	}
430 431 432
	if len(pool.all) != 1 {
		t.Error("expected 1 total transactions, got", len(pool.all))
	}
433
}
434 435 436 437

func TestNonceRecovery(t *testing.T) {
	const n = 10
	pool, key := setupTxPool()
438 439
	defer pool.Stop()

440
	addr := crypto.PubkeyToAddress(key.PublicKey)
441
	currentState, _ := pool.blockChain.State()
442 443
	currentState.SetNonce(addr, n)
	currentState.AddBalance(addr, big.NewInt(100000000000000))
444
	pool.lockedReset()
445
	tx := transaction(n, big.NewInt(100000), key)
446
	if err := pool.AddRemote(tx); err != nil {
447 448 449
		t.Error(err)
	}
	// simulate some weird re-order of transactions and missing nonce(s)
450
	currentState.SetNonce(addr, n-1)
451
	pool.lockedReset()
452 453 454 455
	if fn := pool.pendingState.GetNonce(addr); fn != n+1 {
		t.Errorf("expected nonce to be %d, got %d", n+1, fn)
	}
}
456 457 458

func TestRemovedTxEvent(t *testing.T) {
	pool, key := setupTxPool()
459 460
	defer pool.Stop()

461
	tx := transaction(0, big.NewInt(1000000), key)
462
	from, _ := deriveSender(tx)
463
	currentState, _ := pool.blockChain.State()
464
	currentState.AddBalance(from, big.NewInt(1000000000000))
465
	pool.lockedReset()
466 467 468 469 470
	blockChain, _ := pool.blockChain.(*testBlockChain)
	blockChain.rmTxFeed.Send(RemovedTransactionEvent{types.Transactions{tx}})
	blockChain.chainHeadFeed.Send(ChainHeadEvent{nil})
	// wait for handling events
	<-time.After(500 * time.Millisecond)
471 472
	if pool.pending[from].Len() != 1 {
		t.Error("expected 1 pending tx, got", pool.pending[from].Len())
473 474 475
	}
	if len(pool.all) != 1 {
		t.Error("expected 1 total transactions, got", len(pool.all))
476 477
	}
}
478 479 480 481 482 483

// Tests that if an account runs out of funds, any pending and queued transactions
// are dropped.
func TestTransactionDropping(t *testing.T) {
	// Create a test account and fund it
	pool, key := setupTxPool()
484 485
	defer pool.Stop()

486
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
487

488
	state, _ := pool.blockChain.State()
489 490 491 492 493 494
	state.AddBalance(account, big.NewInt(1000))

	// Add some pending and some queued transactions
	var (
		tx0  = transaction(0, big.NewInt(100), key)
		tx1  = transaction(1, big.NewInt(200), key)
495
		tx2  = transaction(2, big.NewInt(300), key)
496 497
		tx10 = transaction(10, big.NewInt(100), key)
		tx11 = transaction(11, big.NewInt(200), key)
498
		tx12 = transaction(12, big.NewInt(300), key)
499
	)
500 501
	pool.promoteTx(account, tx0.Hash(), tx0)
	pool.promoteTx(account, tx1.Hash(), tx1)
502
	pool.promoteTx(account, tx2.Hash(), tx2)
503 504
	pool.enqueueTx(tx10.Hash(), tx10)
	pool.enqueueTx(tx11.Hash(), tx11)
505
	pool.enqueueTx(tx12.Hash(), tx12)
506 507

	// Check that pre and post validations leave the pool as is
508 509
	if pool.pending[account].Len() != 3 {
		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3)
510
	}
511 512
	if pool.queue[account].Len() != 3 {
		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3)
513
	}
514 515
	if len(pool.all) != 6 {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6)
516
	}
517
	pool.lockedReset()
518 519
	if pool.pending[account].Len() != 3 {
		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), 3)
520
	}
521 522
	if pool.queue[account].Len() != 3 {
		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 3)
523
	}
524 525
	if len(pool.all) != 6 {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 6)
526 527
	}
	// Reduce the balance of the account, and check that invalidated transactions are dropped
528
	state.AddBalance(account, big.NewInt(-650))
529
	pool.lockedReset()
530

531
	if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
532 533
		t.Errorf("funded pending transaction missing: %v", tx0)
	}
534 535 536 537
	if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok {
		t.Errorf("funded pending transaction missing: %v", tx0)
	}
	if _, ok := pool.pending[account].txs.items[tx2.Nonce()]; ok {
538 539
		t.Errorf("out-of-fund pending transaction present: %v", tx1)
	}
540
	if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
541 542
		t.Errorf("funded queued transaction missing: %v", tx10)
	}
543 544 545 546
	if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok {
		t.Errorf("funded queued transaction missing: %v", tx10)
	}
	if _, ok := pool.queue[account].txs.items[tx12.Nonce()]; ok {
547 548
		t.Errorf("out-of-fund queued transaction present: %v", tx11)
	}
549 550 551 552
	if len(pool.all) != 4 {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 4)
	}
	// Reduce the block gas limit, check that invalidated transactions are dropped
553
	pool.blockChain.(*testBlockChain).gasLimit = big.NewInt(100)
554
	pool.lockedReset()
555 556 557 558 559 560 561 562 563 564 565 566 567

	if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
		t.Errorf("funded pending transaction missing: %v", tx0)
	}
	if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok {
		t.Errorf("over-gased pending transaction present: %v", tx1)
	}
	if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
		t.Errorf("funded queued transaction missing: %v", tx10)
	}
	if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok {
		t.Errorf("over-gased queued transaction present: %v", tx11)
	}
568 569 570
	if len(pool.all) != 2 {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), 2)
	}
571 572 573 574
}

// Tests that if a transaction is dropped from the current pending pool (e.g. out
// of fund), all consecutive (still valid, but not executable) transactions are
Leif Jurvetson's avatar
Leif Jurvetson committed
575
// postponed back into the future queue to prevent broadcasting them.
576 577 578
func TestTransactionPostponing(t *testing.T) {
	// Create a test account and fund it
	pool, key := setupTxPool()
579 580
	defer pool.Stop()

581
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
582

583
	state, _ := pool.blockChain.State()
584 585 586 587 588 589 590 591 592 593 594
	state.AddBalance(account, big.NewInt(1000))

	// Add a batch consecutive pending transactions for validation
	txns := []*types.Transaction{}
	for i := 0; i < 100; i++ {
		var tx *types.Transaction
		if i%2 == 0 {
			tx = transaction(uint64(i), big.NewInt(100), key)
		} else {
			tx = transaction(uint64(i), big.NewInt(500), key)
		}
595
		pool.promoteTx(account, tx.Hash(), tx)
596 597 598
		txns = append(txns, tx)
	}
	// Check that pre and post validations leave the pool as is
599 600
	if pool.pending[account].Len() != len(txns) {
		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns))
601
	}
602 603
	if len(pool.queue) != 0 {
		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0)
604 605 606
	}
	if len(pool.all) != len(txns) {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns))
607
	}
608
	pool.lockedReset()
609 610
	if pool.pending[account].Len() != len(txns) {
		t.Errorf("pending transaction mismatch: have %d, want %d", pool.pending[account].Len(), len(txns))
611
	}
612 613
	if len(pool.queue) != 0 {
		t.Errorf("queued transaction mismatch: have %d, want %d", pool.queue[account].Len(), 0)
614 615 616
	}
	if len(pool.all) != len(txns) {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns))
617
	}
618
	// Reduce the balance of the account, and check that transactions are reorganised
619
	state.AddBalance(account, big.NewInt(-750))
620
	pool.lockedReset()
621

622
	if _, ok := pool.pending[account].txs.items[txns[0].Nonce()]; !ok {
623 624
		t.Errorf("tx %d: valid and funded transaction missing from pending pool: %v", 0, txns[0])
	}
625
	if _, ok := pool.queue[account].txs.items[txns[0].Nonce()]; ok {
626 627 628 629
		t.Errorf("tx %d: valid and funded transaction present in future queue: %v", 0, txns[0])
	}
	for i, tx := range txns[1:] {
		if i%2 == 1 {
630
			if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
631 632
				t.Errorf("tx %d: valid but future transaction present in pending pool: %v", i+1, tx)
			}
633
			if _, ok := pool.queue[account].txs.items[tx.Nonce()]; !ok {
634 635 636
				t.Errorf("tx %d: valid but future transaction missing from future queue: %v", i+1, tx)
			}
		} else {
637
			if _, ok := pool.pending[account].txs.items[tx.Nonce()]; ok {
638 639
				t.Errorf("tx %d: out-of-fund transaction present in pending pool: %v", i+1, tx)
			}
640
			if _, ok := pool.queue[account].txs.items[tx.Nonce()]; ok {
641 642 643 644
				t.Errorf("tx %d: out-of-fund transaction present in future queue: %v", i+1, tx)
			}
		}
	}
645 646 647
	if len(pool.all) != len(txns)/2 {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), len(txns)/2)
	}
648 649 650 651
}

// Tests that if the transaction count belonging to a single account goes above
// some threshold, the higher transactions are dropped to prevent DOS attacks.
652
func TestTransactionQueueAccountLimiting(t *testing.T) {
653 654
	// Create a test account and fund it
	pool, key := setupTxPool()
655 656
	defer pool.Stop()

657
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
658

659
	state, _ := pool.blockChain.State()
660
	state.AddBalance(account, big.NewInt(1000000))
661
	pool.lockedReset()
662 663

	// Keep queuing up transactions and make sure all above a limit are dropped
664
	for i := uint64(1); i <= testTxPoolConfig.AccountQueue+5; i++ {
665
		if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil {
666 667 668 669 670
			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
		}
		if len(pool.pending) != 0 {
			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, len(pool.pending), 0)
		}
671
		if i <= testTxPoolConfig.AccountQueue {
672 673
			if pool.queue[account].Len() != int(i) {
				t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), i)
674 675
			}
		} else {
676 677
			if pool.queue[account].Len() != int(testTxPoolConfig.AccountQueue) {
				t.Errorf("tx %d: queue limit mismatch: have %d, want %d", i, pool.queue[account].Len(), testTxPoolConfig.AccountQueue)
678 679 680
			}
		}
	}
681 682
	if len(pool.all) != int(testTxPoolConfig.AccountQueue) {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue)
683 684 685 686 687
	}
}

// Tests that if the transaction count belonging to multiple accounts go above
// some threshold, the higher transactions are dropped to prevent DOS attacks.
688 689 690
//
// This logic should not hold for local transactions, unless the local tracking
// mechanism is disabled.
691
func TestTransactionQueueGlobalLimiting(t *testing.T) {
692 693 694 695 696
	testTransactionQueueGlobalLimiting(t, false)
}
func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) {
	testTransactionQueueGlobalLimiting(t, true)
}
697

698
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) {
699 700
	// Create the pool to test the limit enforcement with
	db, _ := ethdb.NewMemDatabase()
701
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
702
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
703

704
	config := testTxPoolConfig
705 706 707
	config.NoLocals = nolocals
	config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible)

708
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
709
	defer pool.Stop()
710

711
	// Create a number of test accounts and fund them (last one will be the local)
712
	state, _ := pool.blockChain.State()
713 714 715 716 717 718

	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
		state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
	}
719 720
	local := keys[len(keys)-1]

721 722 723
	// Generate and queue a batch of transactions
	nonces := make(map[common.Address]uint64)

724
	txs := make(types.Transactions, 0, 3*config.GlobalQueue)
725
	for len(txs) < cap(txs) {
726
		key := keys[rand.Intn(len(keys)-1)] // skip adding transactions with the local account
727 728 729 730 731 732
		addr := crypto.PubkeyToAddress(key.PublicKey)

		txs = append(txs, transaction(nonces[addr]+1, big.NewInt(100000), key))
		nonces[addr]++
	}
	// Import the batch and verify that limits have been enforced
733
	pool.AddRemotes(txs)
734 735 736

	queued := 0
	for addr, list := range pool.queue {
737 738
		if list.Len() > int(config.AccountQueue) {
			t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue)
739 740 741
		}
		queued += list.Len()
	}
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
	if queued > int(config.GlobalQueue) {
		t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue)
	}
	// Generate a batch of transactions from the local account and import them
	txs = txs[:0]
	for i := uint64(0); i < 3*config.GlobalQueue; i++ {
		txs = append(txs, transaction(i+1, big.NewInt(100000), local))
	}
	pool.AddLocals(txs)

	// If locals are disabled, the previous eviction algorithm should apply here too
	if nolocals {
		queued := 0
		for addr, list := range pool.queue {
			if list.Len() > int(config.AccountQueue) {
				t.Errorf("addr %x: queued accounts overflown allowance: %d > %d", addr, list.Len(), config.AccountQueue)
			}
			queued += list.Len()
		}
		if queued > int(config.GlobalQueue) {
			t.Fatalf("total transactions overflow allowance: %d > %d", queued, config.GlobalQueue)
		}
	} else {
		// Local exemptions are enabled, make sure the local account owned the queue
		if len(pool.queue) != 1 {
			t.Errorf("multiple accounts in queue: have %v, want %v", len(pool.queue), 1)
		}
		// Also ensure no local transactions are ever dropped, even if above global limits
		if queued := pool.queue[crypto.PubkeyToAddress(local.PublicKey)].Len(); uint64(queued) != 3*config.GlobalQueue {
			t.Fatalf("local account queued transaction count mismatch: have %v, want %v", queued, 3*config.GlobalQueue)
		}
773 774 775 776 777 778
	}
}

// Tests that if an account remains idle for a prolonged amount of time, any
// non-executable transactions queued up are dropped to prevent wasting resources
// on shuffling them around.
779 780 781 782 783 784 785 786
//
// This logic should not hold for local transactions, unless the local tracking
// mechanism is disabled.
func TestTransactionQueueTimeLimiting(t *testing.T)         { testTransactionQueueTimeLimiting(t, false) }
func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { testTransactionQueueTimeLimiting(t, true) }

func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) {
	// Reduce the eviction interval to a testable amount
787
	defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
788
	evictionInterval = time.Second
789

790 791 792
	// Create the pool to test the non-expiration enforcement
	db, _ := ethdb.NewMemDatabase()
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
793
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
794

795
	config := testTxPoolConfig
796
	config.Lifetime = time.Second
797 798
	config.NoLocals = nolocals

799
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
800 801 802 803 804
	defer pool.Stop()

	// Create two test accounts to ensure remotes expire but locals do not
	local, _ := crypto.GenerateKey()
	remote, _ := crypto.GenerateKey()
805

806
	state, _ := pool.blockChain.State()
807 808
	state.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
	state.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
809

810 811 812 813 814 815 816
	// Add the two transactions and ensure they both are queued up
	if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil {
		t.Fatalf("failed to add local transaction: %v", err)
	}
	if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
		t.Fatalf("failed to add remote transaction: %v", err)
	}
817
	pending, queued := pool.Stats()
818 819 820 821 822 823 824 825 826 827 828 829
	if pending != 0 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
	}
	if queued != 2 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
	}
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
	// Wait a bit for eviction to run and clean up any leftovers, and ensure only the local remains
	time.Sleep(2 * config.Lifetime)

830
	pending, queued = pool.Stats()
831 832 833 834 835 836 837 838 839 840
	if pending != 0 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
	}
	if nolocals {
		if queued != 0 {
			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
		}
	} else {
		if queued != 1 {
			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
841 842
		}
	}
843 844
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
845
	}
846 847 848 849 850 851 852 853
}

// Tests that even if the transaction count belonging to a single account goes
// above some threshold, as long as the transactions are executable, they are
// accepted.
func TestTransactionPendingLimiting(t *testing.T) {
	// Create a test account and fund it
	pool, key := setupTxPool()
854 855
	defer pool.Stop()

856
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
857

858
	state, _ := pool.blockChain.State()
859
	state.AddBalance(account, big.NewInt(1000000))
860
	pool.lockedReset()
861 862

	// Keep queuing up transactions and make sure all above a limit are dropped
863
	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
864
		if err := pool.AddRemote(transaction(i, big.NewInt(100000), key)); err != nil {
865 866
			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
		}
867 868
		if pool.pending[account].Len() != int(i)+1 {
			t.Errorf("tx %d: pending pool size mismatch: have %d, want %d", i, pool.pending[account].Len(), i+1)
869
		}
870 871
		if len(pool.queue) != 0 {
			t.Errorf("tx %d: queue size mismatch: have %d, want %d", i, pool.queue[account].Len(), 0)
872 873
		}
	}
874 875
	if len(pool.all) != int(testTxPoolConfig.AccountQueue+5) {
		t.Errorf("total transaction mismatch: have %d, want %d", len(pool.all), testTxPoolConfig.AccountQueue+5)
876
	}
877 878 879 880 881 882 883 884 885 886
}

// Tests that the transaction limits are enforced the same way irrelevant whether
// the transactions are added one by one or in batches.
func TestTransactionQueueLimitingEquivalency(t *testing.T)   { testTransactionLimitingEquivalency(t, 1) }
func TestTransactionPendingLimitingEquivalency(t *testing.T) { testTransactionLimitingEquivalency(t, 0) }

func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
	// Add a batch of transactions to a pool one by one
	pool1, key1 := setupTxPool()
887 888
	defer pool1.Stop()

889
	account1, _ := deriveSender(transaction(0, big.NewInt(0), key1))
890
	state1, _ := pool1.blockChain.State()
891 892
	state1.AddBalance(account1, big.NewInt(1000000))

893
	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
894
		if err := pool1.AddRemote(transaction(origin+i, big.NewInt(100000), key1)); err != nil {
895 896 897
			t.Fatalf("tx %d: failed to add transaction: %v", i, err)
		}
	}
898
	// Add a batch of transactions to a pool in one big batch
899
	pool2, key2 := setupTxPool()
900 901
	defer pool2.Stop()

902
	account2, _ := deriveSender(transaction(0, big.NewInt(0), key2))
903
	state2, _ := pool2.blockChain.State()
904 905 906
	state2.AddBalance(account2, big.NewInt(1000000))

	txns := []*types.Transaction{}
907
	for i := uint64(0); i < testTxPoolConfig.AccountQueue+5; i++ {
908 909
		txns = append(txns, transaction(origin+i, big.NewInt(100000), key2))
	}
910
	pool2.AddRemotes(txns)
911 912 913 914 915

	// Ensure the batch optimization honors the same pool mechanics
	if len(pool1.pending) != len(pool2.pending) {
		t.Errorf("pending transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.pending), len(pool2.pending))
	}
916 917
	if len(pool1.queue) != len(pool2.queue) {
		t.Errorf("queued transaction count mismatch: one-by-one algo: %d, batch algo: %d", len(pool1.queue), len(pool2.queue))
918
	}
919 920 921
	if len(pool1.all) != len(pool2.all) {
		t.Errorf("total transaction count mismatch: one-by-one algo %d, batch algo %d", len(pool1.all), len(pool2.all))
	}
922 923 924 925 926 927
	if err := validateTxPoolInternals(pool1); err != nil {
		t.Errorf("pool 1 internal state corrupted: %v", err)
	}
	if err := validateTxPoolInternals(pool2); err != nil {
		t.Errorf("pool 2 internal state corrupted: %v", err)
	}
928 929
}

930 931 932 933 934 935
// Tests that if the transaction count belonging to multiple accounts go above
// some hard threshold, the higher transactions are dropped to prevent DOS
// attacks.
func TestTransactionPendingGlobalLimiting(t *testing.T) {
	// Create the pool to test the limit enforcement with
	db, _ := ethdb.NewMemDatabase()
936
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
937
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
938

939
	config := testTxPoolConfig
940 941
	config.GlobalSlots = config.AccountSlots * 10

942
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
943
	defer pool.Stop()
944 945

	// Create a number of test accounts and fund them
946
	state, _ := pool.blockChain.State()
947 948 949 950 951 952 953 954 955 956 957 958

	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
		state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
	}
	// Generate and queue a batch of transactions
	nonces := make(map[common.Address]uint64)

	txs := types.Transactions{}
	for _, key := range keys {
		addr := crypto.PubkeyToAddress(key.PublicKey)
959
		for j := 0; j < int(config.GlobalSlots)/len(keys)*2; j++ {
960 961 962 963 964
			txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
			nonces[addr]++
		}
	}
	// Import the batch and verify that limits have been enforced
965
	pool.AddRemotes(txs)
966 967 968 969 970

	pending := 0
	for _, list := range pool.pending {
		pending += list.Len()
	}
971 972
	if pending > int(config.GlobalSlots) {
		t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots)
973
	}
974 975 976
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
977 978
}

979 980 981 982
// Tests that if transactions start being capped, transasctions are also removed from 'all'
func TestTransactionCapClearsFromAll(t *testing.T) {
	// Create the pool to test the limit enforcement with
	db, _ := ethdb.NewMemDatabase()
983
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
984
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
985

986
	config := testTxPoolConfig
987 988 989 990
	config.AccountSlots = 2
	config.AccountQueue = 2
	config.GlobalSlots = 8

991
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
992
	defer pool.Stop()
993 994

	// Create a number of test accounts and fund them
995
	state, _ := pool.blockChain.State()
996 997 998 999 1000 1001

	key, _ := crypto.GenerateKey()
	addr := crypto.PubkeyToAddress(key.PublicKey)
	state.AddBalance(addr, big.NewInt(1000000))

	txs := types.Transactions{}
1002
	for j := 0; j < int(config.GlobalSlots)*2; j++ {
1003
		txs = append(txs, transaction(uint64(j), big.NewInt(100000), key))
1004 1005
	}
	// Import the batch and verify that limits have been enforced
1006
	pool.AddRemotes(txs)
1007 1008
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
1009 1010 1011
	}
}

1012 1013 1014 1015 1016 1017
// Tests that if the transaction count belonging to multiple accounts go above
// some hard threshold, if they are under the minimum guaranteed slot count then
// the transactions are still kept.
func TestTransactionPendingMinimumAllowance(t *testing.T) {
	// Create the pool to test the limit enforcement with
	db, _ := ethdb.NewMemDatabase()
1018
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
1019
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
1020

1021
	config := testTxPoolConfig
1022 1023
	config.GlobalSlots = 0

1024
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
1025
	defer pool.Stop()
1026 1027

	// Create a number of test accounts and fund them
1028
	state, _ := pool.blockChain.State()
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040

	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
		state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
	}
	// Generate and queue a batch of transactions
	nonces := make(map[common.Address]uint64)

	txs := types.Transactions{}
	for _, key := range keys {
		addr := crypto.PubkeyToAddress(key.PublicKey)
1041
		for j := 0; j < int(config.AccountSlots)*2; j++ {
1042 1043 1044 1045 1046
			txs = append(txs, transaction(nonces[addr], big.NewInt(100000), key))
			nonces[addr]++
		}
	}
	// Import the batch and verify that limits have been enforced
1047
	pool.AddRemotes(txs)
1048 1049

	for addr, list := range pool.pending {
1050 1051
		if list.Len() != int(config.AccountSlots) {
			t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots)
1052 1053
		}
	}
1054 1055 1056
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1057 1058
}

1059 1060 1061 1062 1063 1064 1065 1066
// Tests that setting the transaction pool gas price to a higher value correctly
// discards everything cheaper than that and moves any gapped transactions back
// from the pending pool to the queue.
//
// Note, local transactions are never allowed to be dropped.
func TestTransactionPoolRepricing(t *testing.T) {
	// Create the pool to test the pricing enforcement with
	db, _ := ethdb.NewMemDatabase()
1067
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
1068
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
1069

1070
	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
1071
	defer pool.Stop()
1072 1073

	// Create a number of test accounts and fund them
1074
	state, _ := pool.blockChain.State()
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091

	keys := make([]*ecdsa.PrivateKey, 3)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
		state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
	}
	// Generate and queue a batch of transactions, both pending and queued
	txs := types.Transactions{}

	txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(2), keys[0]))
	txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0]))
	txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(2), keys[0]))

	txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[1]))
	txs = append(txs, pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1]))
	txs = append(txs, pricedTransaction(3, big.NewInt(100000), big.NewInt(2), keys[1]))

1092
	ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2])
1093 1094

	// Import the batch and that both pending and queued transactions match up
1095 1096
	pool.AddRemotes(txs)
	pool.AddLocal(ltx)
1097

1098
	pending, queued := pool.Stats()
1099 1100 1101 1102 1103 1104
	if pending != 4 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
	}
	if queued != 3 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
	}
1105 1106 1107
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1108 1109 1110
	// Reprice the pool and check that underpriced transactions get dropped
	pool.SetGasPrice(big.NewInt(2))

1111
	pending, queued = pool.Stats()
1112 1113 1114 1115 1116 1117
	if pending != 2 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
	}
	if queued != 3 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
	}
1118 1119 1120
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1121
	// Check that we can't add the old transactions back
1122
	if err := pool.AddRemote(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[0])); err != ErrUnderpriced {
1123 1124
		t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
	}
1125
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced {
1126 1127
		t.Fatalf("adding underpriced queued transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
	}
1128 1129 1130
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1131 1132
	// However we can add local underpriced transactions
	tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[2])
1133
	if err := pool.AddLocal(tx); err != nil {
1134 1135
		t.Fatalf("failed to add underpriced local transaction: %v", err)
	}
1136
	if pending, _ = pool.Stats(); pending != 3 {
1137 1138
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
	}
1139 1140
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
1141
	}
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
}

// Tests that when the pool reaches its global transaction limit, underpriced
// transactions are gradually shifted out for more expensive ones and any gapped
// pending transactions are moved into te queue.
//
// Note, local transactions are never allowed to be dropped.
func TestTransactionPoolUnderpricing(t *testing.T) {
	// Create the pool to test the pricing enforcement with
	db, _ := ethdb.NewMemDatabase()
1152
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
1153
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
1154

1155
	config := testTxPoolConfig
1156 1157 1158
	config.GlobalSlots = 2
	config.GlobalQueue = 2

1159
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
1160
	defer pool.Stop()
1161 1162

	// Create a number of test accounts and fund them
1163
	state, _ := pool.blockChain.State()
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177

	keys := make([]*ecdsa.PrivateKey, 3)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
		state.AddBalance(crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
	}
	// Generate and queue a batch of transactions, both pending and queued
	txs := types.Transactions{}

	txs = append(txs, pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[0]))
	txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(2), keys[0]))

	txs = append(txs, pricedTransaction(1, big.NewInt(100000), big.NewInt(1), keys[1]))

1178
	ltx := pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[2])
1179 1180

	// Import the batch and that both pending and queued transactions match up
1181 1182
	pool.AddRemotes(txs)
	pool.AddLocal(ltx)
1183

1184
	pending, queued := pool.Stats()
1185 1186 1187 1188 1189 1190
	if pending != 3 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
	}
	if queued != 1 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
	}
1191 1192 1193
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1194
	// Ensure that adding an underpriced transaction on block limit fails
1195
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), keys[1])); err != ErrUnderpriced {
1196 1197 1198
		t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, ErrUnderpriced)
	}
	// Ensure that adding high priced transactions drops cheap ones, but not own
1199
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(3), keys[1])); err != nil {
1200 1201
		t.Fatalf("failed to add well priced transaction: %v", err)
	}
1202
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(4), keys[1])); err != nil {
1203 1204
		t.Fatalf("failed to add well priced transaction: %v", err)
	}
1205
	if err := pool.AddRemote(pricedTransaction(3, big.NewInt(100000), big.NewInt(5), keys[1])); err != nil {
1206 1207
		t.Fatalf("failed to add well priced transaction: %v", err)
	}
1208
	pending, queued = pool.Stats()
1209 1210 1211 1212 1213 1214
	if pending != 2 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
	}
	if queued != 2 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
	}
1215 1216 1217
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1218 1219
	// Ensure that adding local transactions can push out even higher priced ones
	tx := pricedTransaction(1, big.NewInt(100000), big.NewInt(0), keys[2])
1220
	if err := pool.AddLocal(tx); err != nil {
1221 1222
		t.Fatalf("failed to add underpriced local transaction: %v", err)
	}
1223
	pending, queued = pool.Stats()
1224 1225 1226 1227 1228 1229
	if pending != 2 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
	}
	if queued != 2 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
	}
1230 1231
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
1232
	}
1233 1234 1235 1236 1237 1238 1239
}

// Tests that the pool rejects replacement transactions that don't meet the minimum
// price bump required.
func TestTransactionReplacement(t *testing.T) {
	// Create the pool to test the pricing enforcement with
	db, _ := ethdb.NewMemDatabase()
1240
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
1241
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
1242

1243
	pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain)
1244
	defer pool.Stop()
1245

1246
	// Create a test account to add transactions with
1247 1248
	key, _ := crypto.GenerateKey()

1249
	state, _ := pool.blockChain.State()
1250 1251 1252 1253
	state.AddBalance(crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000))

	// Add pending transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too)
	price := int64(100)
1254
	threshold := (price * (100 + int64(testTxPoolConfig.PriceBump))) / 100
1255

1256
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), key)); err != nil {
1257 1258
		t.Fatalf("failed to add original cheap pending transaction: %v", err)
	}
1259
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced {
1260 1261
		t.Fatalf("original cheap pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
	}
1262
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(2), key)); err != nil {
1263 1264 1265
		t.Fatalf("failed to replace original cheap pending transaction: %v", err)
	}

1266
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(price), key)); err != nil {
1267 1268
		t.Fatalf("failed to add original proper pending transaction: %v", err)
	}
1269
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold), key)); err != ErrReplaceUnderpriced {
1270 1271
		t.Fatalf("original proper pending transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
	}
1272
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(threshold+1), key)); err != nil {
1273 1274 1275
		t.Fatalf("failed to replace original proper pending transaction: %v", err)
	}
	// Add queued transactions, ensuring the minimum price bump is enforced for replacement (for ultra low prices too)
1276
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), key)); err != nil {
1277 1278
		t.Fatalf("failed to add original queued transaction: %v", err)
	}
1279
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(1), key)); err != ErrReplaceUnderpriced {
1280 1281
		t.Fatalf("original queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
	}
1282
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(2), key)); err != nil {
1283 1284 1285
		t.Fatalf("failed to replace original queued transaction: %v", err)
	}

1286
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(price), key)); err != nil {
1287 1288
		t.Fatalf("failed to add original queued transaction: %v", err)
	}
1289
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100001), big.NewInt(threshold), key)); err != ErrReplaceUnderpriced {
1290 1291
		t.Fatalf("original queued transaction replacement error mismatch: have %v, want %v", err, ErrReplaceUnderpriced)
	}
1292
	if err := pool.AddRemote(pricedTransaction(2, big.NewInt(100000), big.NewInt(threshold+1), key)); err != nil {
1293 1294
		t.Fatalf("failed to replace original queued transaction: %v", err)
	}
1295 1296
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
1297
	}
1298 1299
}

1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
// Tests that local transactions are journaled to disk, but remote transactions
// get discarded between restarts.
func TestTransactionJournaling(t *testing.T)         { testTransactionJournaling(t, false) }
func TestTransactionJournalingNoLocals(t *testing.T) { testTransactionJournaling(t, true) }

func testTransactionJournaling(t *testing.T, nolocals bool) {
	// Create a temporary file for the journal
	file, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatalf("failed to create temporary journal: %v", err)
	}
	journal := file.Name()
	defer os.Remove(journal)

	// Clean up the temporary file, we only need the path for now
	file.Close()
	os.Remove(journal)

	// Create the original pool to inject transaction into the journal
	db, _ := ethdb.NewMemDatabase()
	statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
1321
	blockchain := &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
1322 1323 1324 1325 1326 1327

	config := testTxPoolConfig
	config.NoLocals = nolocals
	config.Journal = journal
	config.Rejournal = time.Second

1328
	pool := NewTxPool(config, params.TestChainConfig, blockchain)
1329 1330 1331 1332 1333

	// Create two test accounts to ensure remotes expire but locals do not
	local, _ := crypto.GenerateKey()
	remote, _ := crypto.GenerateKey()

1334
	statedb, _ = pool.blockChain.State()
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
	statedb.AddBalance(crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
	statedb.AddBalance(crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))

	// Add three local and a remote transactions and ensure they are queued up
	if err := pool.AddLocal(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), local)); err != nil {
		t.Fatalf("failed to add local transaction: %v", err)
	}
	if err := pool.AddLocal(pricedTransaction(1, big.NewInt(100000), big.NewInt(1), local)); err != nil {
		t.Fatalf("failed to add local transaction: %v", err)
	}
	if err := pool.AddLocal(pricedTransaction(2, big.NewInt(100000), big.NewInt(1), local)); err != nil {
		t.Fatalf("failed to add local transaction: %v", err)
	}
	if err := pool.AddRemote(pricedTransaction(0, big.NewInt(100000), big.NewInt(1), remote)); err != nil {
		t.Fatalf("failed to add remote transaction: %v", err)
	}
1351
	pending, queued := pool.Stats()
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
	if pending != 4 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
	}
	if queued != 0 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
	}
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
	// Terminate the old pool, bump the local nonce, create a new pool and ensure relevant transaction survive
	pool.Stop()
	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
1364 1365
	blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
	pool = NewTxPool(config, params.TestChainConfig, blockchain)
1366

1367
	pending, queued = pool.Stats()
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
	if queued != 0 {
		t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
	}
	if nolocals {
		if pending != 0 {
			t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
		}
	} else {
		if pending != 2 {
			t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
		}
	}
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
	// Bump the nonce temporarily and ensure the newly invalidated transaction is removed
	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2)
1385
	pool.lockedReset()
1386 1387 1388
	time.Sleep(2 * config.Rejournal)
	pool.Stop()
	statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
1389 1390
	blockchain = &testBlockChain{statedb, big.NewInt(1000000), new(event.Feed), new(event.Feed)}
	pool = NewTxPool(config, params.TestChainConfig, blockchain)
1391

1392
	pending, queued = pool.Stats()
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
	if pending != 0 {
		t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
	}
	if nolocals {
		if queued != 0 {
			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
		}
	} else {
		if queued != 1 {
			t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
		}
	}
	if err := validateTxPoolInternals(pool); err != nil {
		t.Fatalf("pool internal state corrupted: %v", err)
	}
1408
	pool.Stop()
1409 1410
}

1411 1412
// Benchmarks the speed of validating the contents of the pending queue of the
// transaction pool.
1413 1414 1415
func BenchmarkPendingDemotion100(b *testing.B)   { benchmarkPendingDemotion(b, 100) }
func BenchmarkPendingDemotion1000(b *testing.B)  { benchmarkPendingDemotion(b, 1000) }
func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 10000) }
1416

1417
func benchmarkPendingDemotion(b *testing.B, size int) {
1418 1419
	// Add a batch of transactions to a pool one by one
	pool, key := setupTxPool()
1420 1421
	defer pool.Stop()

1422
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
1423
	state, _ := pool.blockChain.State()
1424 1425 1426 1427
	state.AddBalance(account, big.NewInt(1000000))

	for i := 0; i < size; i++ {
		tx := transaction(uint64(i), big.NewInt(100000), key)
1428
		pool.promoteTx(account, tx.Hash(), tx)
1429 1430 1431 1432
	}
	// Benchmark the speed of pool validation
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
1433
		pool.demoteUnexecutables(state)
1434 1435 1436 1437 1438
	}
}

// Benchmarks the speed of scheduling the contents of the future queue of the
// transaction pool.
1439 1440 1441
func BenchmarkFuturePromotion100(b *testing.B)   { benchmarkFuturePromotion(b, 100) }
func BenchmarkFuturePromotion1000(b *testing.B)  { benchmarkFuturePromotion(b, 1000) }
func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 10000) }
1442

1443
func benchmarkFuturePromotion(b *testing.B, size int) {
1444 1445
	// Add a batch of transactions to a pool one by one
	pool, key := setupTxPool()
1446 1447
	defer pool.Stop()

1448
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
1449
	state, _ := pool.blockChain.State()
1450 1451 1452 1453
	state.AddBalance(account, big.NewInt(1000000))

	for i := 0; i < size; i++ {
		tx := transaction(uint64(1+i), big.NewInt(100000), key)
1454
		pool.enqueueTx(tx.Hash(), tx)
1455 1456 1457 1458
	}
	// Benchmark the speed of pool validation
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
1459
		pool.promoteExecutables(state, nil)
1460 1461 1462 1463 1464 1465 1466
	}
}

// Benchmarks the speed of iterative transaction insertion.
func BenchmarkPoolInsert(b *testing.B) {
	// Generate a batch of transactions to enqueue into the pool
	pool, key := setupTxPool()
1467 1468
	defer pool.Stop()

1469
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
1470
	state, _ := pool.blockChain.State()
1471 1472 1473 1474 1475 1476 1477 1478 1479
	state.AddBalance(account, big.NewInt(1000000))

	txs := make(types.Transactions, b.N)
	for i := 0; i < b.N; i++ {
		txs[i] = transaction(uint64(i), big.NewInt(100000), key)
	}
	// Benchmark importing the transactions into the queue
	b.ResetTimer()
	for _, tx := range txs {
1480
		pool.AddRemote(tx)
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491
	}
}

// Benchmarks the speed of batched transaction insertion.
func BenchmarkPoolBatchInsert100(b *testing.B)   { benchmarkPoolBatchInsert(b, 100) }
func BenchmarkPoolBatchInsert1000(b *testing.B)  { benchmarkPoolBatchInsert(b, 1000) }
func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000) }

func benchmarkPoolBatchInsert(b *testing.B, size int) {
	// Generate a batch of transactions to enqueue into the pool
	pool, key := setupTxPool()
1492 1493
	defer pool.Stop()

1494
	account, _ := deriveSender(transaction(0, big.NewInt(0), key))
1495
	state, _ := pool.blockChain.State()
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
	state.AddBalance(account, big.NewInt(1000000))

	batches := make([]types.Transactions, b.N)
	for i := 0; i < b.N; i++ {
		batches[i] = make(types.Transactions, size)
		for j := 0; j < size; j++ {
			batches[i][j] = transaction(uint64(size*i+j), big.NewInt(100000), key)
		}
	}
	// Benchmark importing the transactions into the queue
	b.ResetTimer()
	for _, batch := range batches {
1508
		pool.AddRemotes(batch)
1509 1510
	}
}