core/txpool/legacypool: get the tests in order
This commit is contained in:
parent
c2efd6fc19
commit
183fc1085e
|
@ -397,7 +397,7 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
|
||||||
// If the min miner fee increased, remove transactions below the new threshold
|
// If the min miner fee increased, remove transactions below the new threshold
|
||||||
if newTip.Cmp(old) > 0 {
|
if newTip.Cmp(old) > 0 {
|
||||||
// pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead
|
// pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead
|
||||||
drop := pool.all.RemotesBelowTip(tip)
|
drop := pool.all.TxsBelowTip(tip)
|
||||||
for _, tx := range drop {
|
for _, tx := range drop {
|
||||||
pool.removeTx(tx.Hash(), false, true)
|
pool.removeTx(tx.Hash(), false, true)
|
||||||
}
|
}
|
||||||
|
@ -1685,14 +1685,6 @@ func (t *lookup) Get(hash common.Hash) *types.Transaction {
|
||||||
return t.remotes[hash]
|
return t.remotes[hash]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRemote returns a transaction if it exists in the lookup, or nil if not found.
|
|
||||||
func (t *lookup) GetRemote(hash common.Hash) *types.Transaction {
|
|
||||||
t.lock.RLock()
|
|
||||||
defer t.lock.RUnlock()
|
|
||||||
|
|
||||||
return t.remotes[hash]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count returns the current number of transactions in the lookup.
|
// Count returns the current number of transactions in the lookup.
|
||||||
func (t *lookup) Count() int {
|
func (t *lookup) Count() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
|
@ -1701,14 +1693,6 @@ func (t *lookup) Count() int {
|
||||||
return len(t.remotes)
|
return len(t.remotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteCount returns the current number of remote transactions in the lookup.
|
|
||||||
func (t *lookup) RemoteCount() int {
|
|
||||||
t.lock.RLock()
|
|
||||||
defer t.lock.RUnlock()
|
|
||||||
|
|
||||||
return len(t.remotes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slots returns the current number of slots used in the lookup.
|
// Slots returns the current number of slots used in the lookup.
|
||||||
func (t *lookup) Slots() int {
|
func (t *lookup) Slots() int {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
|
@ -1744,8 +1728,8 @@ func (t *lookup) Remove(hash common.Hash) {
|
||||||
delete(t.remotes, hash)
|
delete(t.remotes, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemotesBelowTip finds all remote transactions below the given tip threshold.
|
// TxsBelowTip finds all remote transactions below the given tip threshold.
|
||||||
func (t *lookup) RemotesBelowTip(threshold *big.Int) types.Transactions {
|
func (t *lookup) TxsBelowTip(threshold *big.Int) types.Transactions {
|
||||||
found := make(types.Transactions, 0, 128)
|
found := make(types.Transactions, 0, 128)
|
||||||
t.Range(func(hash common.Hash, tx *types.Transaction) bool {
|
t.Range(func(hash common.Hash, tx *types.Transaction) bool {
|
||||||
if tx.GasTipCapIntCmp(threshold) < 0 {
|
if tx.GasTipCapIntCmp(threshold) < 0 {
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -183,7 +182,7 @@ func validatePoolInternals(pool *LegacyPool) error {
|
||||||
return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued)
|
return fmt.Errorf("total transaction count %d != %d pending + %d queued", total, pending, queued)
|
||||||
}
|
}
|
||||||
pool.priced.Reheap()
|
pool.priced.Reheap()
|
||||||
priced, remote := pool.priced.urgent.Len()+pool.priced.floating.Len(), pool.all.RemoteCount()
|
priced, remote := pool.priced.urgent.Len()+pool.priced.floating.Len(), pool.all.Count()
|
||||||
if priced != remote {
|
if priced != remote {
|
||||||
return fmt.Errorf("total priced transaction count %d != %d", priced, remote)
|
return fmt.Errorf("total priced transaction count %d != %d", priced, remote)
|
||||||
}
|
}
|
||||||
|
@ -350,9 +349,6 @@ func TestInvalidTransactions(t *testing.T) {
|
||||||
if err, want := pool.addRemote(tx), txpool.ErrUnderpriced; !errors.Is(err, want) {
|
if err, want := pool.addRemote(tx), txpool.ErrUnderpriced; !errors.Is(err, want) {
|
||||||
t.Errorf("want %v have %v", want, err)
|
t.Errorf("want %v have %v", want, err)
|
||||||
}
|
}
|
||||||
if err := pool.addLocal(tx); err != nil {
|
|
||||||
t.Error("expected", nil, "got", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueue(t *testing.T) {
|
func TestQueue(t *testing.T) {
|
||||||
|
@ -366,7 +362,7 @@ func TestQueue(t *testing.T) {
|
||||||
testAddBalance(pool, from, big.NewInt(1000))
|
testAddBalance(pool, from, big.NewInt(1000))
|
||||||
<-pool.requestReset(nil, nil)
|
<-pool.requestReset(nil, nil)
|
||||||
|
|
||||||
pool.enqueueTx(tx.Hash(), tx, false, true)
|
pool.enqueueTx(tx.Hash(), tx, true)
|
||||||
<-pool.requestPromoteExecutables(newAccountSet(pool.signer, from))
|
<-pool.requestPromoteExecutables(newAccountSet(pool.signer, from))
|
||||||
if len(pool.pending) != 1 {
|
if len(pool.pending) != 1 {
|
||||||
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
t.Error("expected valid txs to be 1 is", len(pool.pending))
|
||||||
|
@ -375,7 +371,7 @@ func TestQueue(t *testing.T) {
|
||||||
tx = transaction(1, 100, key)
|
tx = transaction(1, 100, key)
|
||||||
from, _ = deriveSender(tx)
|
from, _ = deriveSender(tx)
|
||||||
testSetNonce(pool, from, 2)
|
testSetNonce(pool, from, 2)
|
||||||
pool.enqueueTx(tx.Hash(), tx, false, true)
|
pool.enqueueTx(tx.Hash(), tx, true)
|
||||||
|
|
||||||
<-pool.requestPromoteExecutables(newAccountSet(pool.signer, from))
|
<-pool.requestPromoteExecutables(newAccountSet(pool.signer, from))
|
||||||
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
|
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
|
||||||
|
@ -399,9 +395,9 @@ func TestQueue2(t *testing.T) {
|
||||||
testAddBalance(pool, from, big.NewInt(1000))
|
testAddBalance(pool, from, big.NewInt(1000))
|
||||||
pool.reset(nil, nil)
|
pool.reset(nil, nil)
|
||||||
|
|
||||||
pool.enqueueTx(tx1.Hash(), tx1, false, true)
|
pool.enqueueTx(tx1.Hash(), tx1, true)
|
||||||
pool.enqueueTx(tx2.Hash(), tx2, false, true)
|
pool.enqueueTx(tx2.Hash(), tx2, true)
|
||||||
pool.enqueueTx(tx3.Hash(), tx3, false, true)
|
pool.enqueueTx(tx3.Hash(), tx3, true)
|
||||||
|
|
||||||
pool.promoteExecutables([]common.Address{from})
|
pool.promoteExecutables([]common.Address{from})
|
||||||
if len(pool.pending) != 1 {
|
if len(pool.pending) != 1 {
|
||||||
|
@ -476,14 +472,14 @@ func TestChainFork(t *testing.T) {
|
||||||
resetState()
|
resetState()
|
||||||
|
|
||||||
tx := transaction(0, 100000, key)
|
tx := transaction(0, 100000, key)
|
||||||
if _, err := pool.add(tx, false); err != nil {
|
if _, err := pool.add(tx); err != nil {
|
||||||
t.Error("didn't expect error", err)
|
t.Error("didn't expect error", err)
|
||||||
}
|
}
|
||||||
pool.removeTx(tx.Hash(), true, true)
|
pool.removeTx(tx.Hash(), true, true)
|
||||||
|
|
||||||
// reset the pool's internal state
|
// reset the pool's internal state
|
||||||
resetState()
|
resetState()
|
||||||
if _, err := pool.add(tx, false); err != nil {
|
if _, err := pool.add(tx); err != nil {
|
||||||
t.Error("didn't expect error", err)
|
t.Error("didn't expect error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,10 +506,10 @@ func TestDoubleNonce(t *testing.T) {
|
||||||
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key)
|
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(1), nil), signer, key)
|
||||||
|
|
||||||
// Add the first two transaction, ensure higher priced stays only
|
// Add the first two transaction, ensure higher priced stays only
|
||||||
if replace, err := pool.add(tx1, false); err != nil || replace {
|
if replace, err := pool.add(tx1); err != nil || replace {
|
||||||
t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace)
|
t.Errorf("first transaction insert failed (%v) or reported replacement (%v)", err, replace)
|
||||||
}
|
}
|
||||||
if replace, err := pool.add(tx2, false); err != nil || !replace {
|
if replace, err := pool.add(tx2); err != nil || !replace {
|
||||||
t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
|
t.Errorf("second transaction insert failed (%v) or not reported replacement (%v)", err, replace)
|
||||||
}
|
}
|
||||||
<-pool.requestPromoteExecutables(newAccountSet(signer, addr))
|
<-pool.requestPromoteExecutables(newAccountSet(signer, addr))
|
||||||
|
@ -525,7 +521,7 @@ func TestDoubleNonce(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the third transaction and ensure it's not saved (smaller price)
|
// Add the third transaction and ensure it's not saved (smaller price)
|
||||||
pool.add(tx3, false)
|
pool.add(tx3)
|
||||||
<-pool.requestPromoteExecutables(newAccountSet(signer, addr))
|
<-pool.requestPromoteExecutables(newAccountSet(signer, addr))
|
||||||
if pool.pending[addr].Len() != 1 {
|
if pool.pending[addr].Len() != 1 {
|
||||||
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
|
||||||
|
@ -548,7 +544,7 @@ func TestMissingNonce(t *testing.T) {
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||||
testAddBalance(pool, addr, big.NewInt(100000000000000))
|
testAddBalance(pool, addr, big.NewInt(100000000000000))
|
||||||
tx := transaction(1, 100000, key)
|
tx := transaction(1, 100000, key)
|
||||||
if _, err := pool.add(tx, false); err != nil {
|
if _, err := pool.add(tx); err != nil {
|
||||||
t.Error("didn't expect error", err)
|
t.Error("didn't expect error", err)
|
||||||
}
|
}
|
||||||
if len(pool.pending) != 0 {
|
if len(pool.pending) != 0 {
|
||||||
|
@ -607,21 +603,21 @@ func TestDropping(t *testing.T) {
|
||||||
tx11 = transaction(11, 200, key)
|
tx11 = transaction(11, 200, key)
|
||||||
tx12 = transaction(12, 300, key)
|
tx12 = transaction(12, 300, key)
|
||||||
)
|
)
|
||||||
pool.all.Add(tx0, false)
|
pool.all.Add(tx0)
|
||||||
pool.priced.Put(tx0, false)
|
pool.priced.Put(tx0)
|
||||||
pool.promoteTx(account, tx0.Hash(), tx0)
|
pool.promoteTx(account, tx0.Hash(), tx0)
|
||||||
|
|
||||||
pool.all.Add(tx1, false)
|
pool.all.Add(tx1)
|
||||||
pool.priced.Put(tx1, false)
|
pool.priced.Put(tx1)
|
||||||
pool.promoteTx(account, tx1.Hash(), tx1)
|
pool.promoteTx(account, tx1.Hash(), tx1)
|
||||||
|
|
||||||
pool.all.Add(tx2, false)
|
pool.all.Add(tx2)
|
||||||
pool.priced.Put(tx2, false)
|
pool.priced.Put(tx2)
|
||||||
pool.promoteTx(account, tx2.Hash(), tx2)
|
pool.promoteTx(account, tx2.Hash(), tx2)
|
||||||
|
|
||||||
pool.enqueueTx(tx10.Hash(), tx10, false, true)
|
pool.enqueueTx(tx10.Hash(), tx10, true)
|
||||||
pool.enqueueTx(tx11.Hash(), tx11, false, true)
|
pool.enqueueTx(tx11.Hash(), tx11, true)
|
||||||
pool.enqueueTx(tx12.Hash(), tx12, false, true)
|
pool.enqueueTx(tx12.Hash(), tx12, true)
|
||||||
|
|
||||||
// Check that pre and post validations leave the pool as is
|
// Check that pre and post validations leave the pool as is
|
||||||
if pool.pending[account].Len() != 3 {
|
if pool.pending[account].Len() != 3 {
|
||||||
|
@ -899,13 +895,6 @@ func TestQueueAccountLimiting(t *testing.T) {
|
||||||
// This logic should not hold for local transactions, unless the local tracking
|
// This logic should not hold for local transactions, unless the local tracking
|
||||||
// mechanism is disabled.
|
// mechanism is disabled.
|
||||||
func TestQueueGlobalLimiting(t *testing.T) {
|
func TestQueueGlobalLimiting(t *testing.T) {
|
||||||
testQueueGlobalLimiting(t, false)
|
|
||||||
}
|
|
||||||
func TestQueueGlobalLimitingNoLocals(t *testing.T) {
|
|
||||||
testQueueGlobalLimiting(t, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Create the pool to test the limit enforcement with
|
// Create the pool to test the limit enforcement with
|
||||||
|
@ -913,7 +902,7 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
config.NoLocals = nolocals
|
config.NoLocals = true
|
||||||
config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible)
|
config.GlobalQueue = config.AccountQueue*3 - 1 // reduce the queue limits to shorten test time (-1 to make it non divisible)
|
||||||
|
|
||||||
pool := New(config, blockchain)
|
pool := New(config, blockchain)
|
||||||
|
@ -926,7 +915,6 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
keys[i], _ = crypto.GenerateKey()
|
keys[i], _ = crypto.GenerateKey()
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
|
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
|
||||||
}
|
}
|
||||||
local := keys[len(keys)-1]
|
|
||||||
|
|
||||||
// Generate and queue a batch of transactions
|
// Generate and queue a batch of transactions
|
||||||
nonces := make(map[common.Address]uint64)
|
nonces := make(map[common.Address]uint64)
|
||||||
|
@ -952,51 +940,12 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||||
if queued > int(config.GlobalQueue) {
|
if queued > int(config.GlobalQueue) {
|
||||||
t.Fatalf("total transactions overflow allowance: %d > %d", queued, 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, 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that if an account remains idle for a prolonged amount of time, any
|
// 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
|
// non-executable transactions queued up are dropped to prevent wasting resources
|
||||||
// on shuffling them around.
|
// on shuffling them around.
|
||||||
//
|
|
||||||
// This logic should not hold for local transactions, unless the local tracking
|
|
||||||
// mechanism is disabled.
|
|
||||||
func TestQueueTimeLimiting(t *testing.T) {
|
func TestQueueTimeLimiting(t *testing.T) {
|
||||||
testQueueTimeLimiting(t, false)
|
|
||||||
}
|
|
||||||
func TestQueueTimeLimitingNoLocals(t *testing.T) {
|
|
||||||
testQueueTimeLimiting(t, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
|
||||||
// Reduce the eviction interval to a testable amount
|
// Reduce the eviction interval to a testable amount
|
||||||
defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
|
defer func(old time.Duration) { evictionInterval = old }(evictionInterval)
|
||||||
evictionInterval = time.Millisecond * 100
|
evictionInterval = time.Millisecond * 100
|
||||||
|
@ -1007,23 +956,17 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
|
|
||||||
config := testTxPoolConfig
|
config := testTxPoolConfig
|
||||||
config.Lifetime = time.Second
|
config.Lifetime = time.Second
|
||||||
config.NoLocals = nolocals
|
|
||||||
|
|
||||||
pool := New(config, blockchain)
|
pool := New(config, blockchain)
|
||||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||||
defer pool.Close()
|
defer pool.Close()
|
||||||
|
|
||||||
// Create two test accounts to ensure remotes expire but locals do not
|
// Create a test account to ensure remotes expire
|
||||||
local, _ := crypto.GenerateKey()
|
|
||||||
remote, _ := crypto.GenerateKey()
|
remote, _ := crypto.GenerateKey()
|
||||||
|
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
|
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
|
testAddBalance(pool, crypto.PubkeyToAddress(remote.PublicKey), big.NewInt(1000000000))
|
||||||
|
|
||||||
// Add the two transactions and ensure they both are queued up
|
// Add the transaction and ensure it is queued up
|
||||||
if err := pool.addLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
|
if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(1), remote)); err != nil {
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
t.Fatalf("failed to add remote transaction: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1031,7 +974,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if pending != 0 {
|
if pending != 0 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 1 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
|
@ -1046,7 +989,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if pending != 0 {
|
if pending != 0 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 1 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
|
@ -1060,14 +1003,8 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
if pending != 0 {
|
if pending != 0 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 0)
|
||||||
}
|
}
|
||||||
if nolocals {
|
if queued != 0 {
|
||||||
if queued != 0 {
|
t.Fatalf("queued transactions mismatched: have %d, want %d", 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 := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
|
@ -1075,7 +1012,6 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
|
|
||||||
// remove current transactions and increase nonce to prepare for a reset and cleanup
|
// remove current transactions and increase nonce to prepare for a reset and cleanup
|
||||||
statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2)
|
statedb.SetNonce(crypto.PubkeyToAddress(remote.PublicKey), 2)
|
||||||
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 2)
|
|
||||||
<-pool.requestReset(nil, nil)
|
<-pool.requestReset(nil, nil)
|
||||||
|
|
||||||
// make sure queue, pending are cleared
|
// make sure queue, pending are cleared
|
||||||
|
@ -1091,18 +1027,12 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Queue gapped transactions
|
// Queue gapped transactions
|
||||||
if err := pool.addLocal(pricedTransaction(4, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addRemoteSync(pricedTransaction(4, 100000, big.NewInt(1), remote)); err != nil {
|
if err := pool.addRemoteSync(pricedTransaction(4, 100000, big.NewInt(1), remote)); err != nil {
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
t.Fatalf("failed to add remote transaction: %v", err)
|
||||||
}
|
}
|
||||||
time.Sleep(5 * evictionInterval) // A half lifetime pass
|
time.Sleep(5 * evictionInterval) // A half lifetime pass
|
||||||
|
|
||||||
// Queue executable transactions, the life cycle should be restarted.
|
// Queue executable transactions, the life cycle should be restarted.
|
||||||
if err := pool.addLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), remote)); err != nil {
|
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(1), remote)); err != nil {
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
t.Fatalf("failed to add remote transaction: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1110,11 +1040,11 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
|
|
||||||
// All gapped transactions shouldn't be kicked out
|
// All gapped transactions shouldn't be kicked out
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 1 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 1 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
|
@ -1123,17 +1053,11 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
// The whole life time pass after last promotion, kick out stale transactions
|
// The whole life time pass after last promotion, kick out stale transactions
|
||||||
time.Sleep(2 * config.Lifetime)
|
time.Sleep(2 * config.Lifetime)
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 1 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
|
||||||
}
|
}
|
||||||
if nolocals {
|
if queued != 0 {
|
||||||
if queued != 0 {
|
t.Fatalf("queued transactions mismatched: have %d, want %d", 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 := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
|
@ -1368,8 +1292,6 @@ func TestPendingMinimumAllowance(t *testing.T) {
|
||||||
// Tests that setting the transaction pool gas price to a higher value correctly
|
// Tests that setting the transaction pool gas price to a higher value correctly
|
||||||
// discards everything cheaper than that and moves any gapped transactions back
|
// discards everything cheaper than that and moves any gapped transactions back
|
||||||
// from the pending pool to the queue.
|
// from the pending pool to the queue.
|
||||||
//
|
|
||||||
// Note, local transactions are never allowed to be dropped.
|
|
||||||
func TestRepricing(t *testing.T) {
|
func TestRepricing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -1387,7 +1309,7 @@ func TestRepricing(t *testing.T) {
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
|
|
||||||
// Create a number of test accounts and fund them
|
// Create a number of test accounts and fund them
|
||||||
keys := make([]*ecdsa.PrivateKey, 4)
|
keys := make([]*ecdsa.PrivateKey, 3)
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
keys[i], _ = crypto.GenerateKey()
|
keys[i], _ = crypto.GenerateKey()
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
|
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
|
||||||
|
@ -1407,20 +1329,17 @@ func TestRepricing(t *testing.T) {
|
||||||
txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2]))
|
txs = append(txs, pricedTransaction(2, 100000, big.NewInt(1), keys[2]))
|
||||||
txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2]))
|
txs = append(txs, pricedTransaction(3, 100000, big.NewInt(2), keys[2]))
|
||||||
|
|
||||||
ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[3])
|
|
||||||
|
|
||||||
// Import the batch and that both pending and queued transactions match up
|
// Import the batch and that both pending and queued transactions match up
|
||||||
pool.addRemotesSync(txs)
|
pool.addRemotesSync(txs)
|
||||||
pool.addLocal(ltx)
|
|
||||||
|
|
||||||
pending, queued := pool.Stats()
|
pending, queued := pool.Stats()
|
||||||
if pending != 7 {
|
if pending != 6 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 6)
|
||||||
}
|
}
|
||||||
if queued != 3 {
|
if queued != 3 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
||||||
}
|
}
|
||||||
if err := validateEvents(events, 7); err != nil {
|
if err := validateEvents(events, 6); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
|
@ -1430,8 +1349,8 @@ func TestRepricing(t *testing.T) {
|
||||||
pool.SetGasTip(big.NewInt(2))
|
pool.SetGasTip(big.NewInt(2))
|
||||||
|
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 1 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
|
||||||
}
|
}
|
||||||
if queued != 5 {
|
if queued != 5 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5)
|
||||||
|
@ -1458,21 +1377,7 @@ func TestRepricing(t *testing.T) {
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// However we can add local underpriced transactions
|
// we can fill gaps with properly priced transactions
|
||||||
tx := pricedTransaction(1, 100000, big.NewInt(1), keys[3])
|
|
||||||
if err := pool.addLocal(tx); err != nil {
|
|
||||||
t.Fatalf("failed to add underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if pending, _ = pool.Stats(); pending != 3 {
|
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
|
|
||||||
}
|
|
||||||
if err := validateEvents(events, 1); err != nil {
|
|
||||||
t.Fatalf("post-reprice local event firing failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
// And we can fill gaps with properly priced transactions
|
|
||||||
if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil {
|
if err := pool.addRemote(pricedTransaction(1, 100000, big.NewInt(2), keys[0])); err != nil {
|
||||||
t.Fatalf("failed to add pending transaction: %v", err)
|
t.Fatalf("failed to add pending transaction: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1509,29 +1414,16 @@ func TestMinGasPriceEnforced(t *testing.T) {
|
||||||
tx := pricedTransaction(0, 100000, big.NewInt(2), key)
|
tx := pricedTransaction(0, 100000, big.NewInt(2), key)
|
||||||
pool.SetGasTip(big.NewInt(tx.GasPrice().Int64() + 1))
|
pool.SetGasTip(big.NewInt(tx.GasPrice().Int64() + 1))
|
||||||
|
|
||||||
if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) {
|
if err := pool.Add([]*types.Transaction{tx}, true)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
|
||||||
t.Fatalf("Min tip not enforced")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
|
|
||||||
t.Fatalf("Min tip not enforced")
|
t.Fatalf("Min tip not enforced")
|
||||||
}
|
}
|
||||||
|
|
||||||
tx = dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), key)
|
tx = dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), key)
|
||||||
pool.SetGasTip(big.NewInt(tx.GasTipCap().Int64() + 1))
|
pool.SetGasTip(big.NewInt(tx.GasTipCap().Int64() + 1))
|
||||||
|
|
||||||
if err := pool.addLocal(tx); !errors.Is(err, txpool.ErrUnderpriced) {
|
if err := pool.Add([]*types.Transaction{tx}, true)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
|
||||||
t.Fatalf("Min tip not enforced")
|
t.Fatalf("Min tip not enforced")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; !errors.Is(err, txpool.ErrUnderpriced) {
|
|
||||||
t.Fatalf("Min tip not enforced")
|
|
||||||
}
|
|
||||||
// Make sure the tx is accepted if locals are enabled
|
|
||||||
pool.config.NoLocals = false
|
|
||||||
if err := pool.Add([]*types.Transaction{tx}, true, false)[0]; err != nil {
|
|
||||||
t.Fatalf("Min tip enforced with locals enabled, error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that setting the transaction pool gas price to a higher value correctly
|
// Tests that setting the transaction pool gas price to a higher value correctly
|
||||||
|
@ -1572,20 +1464,17 @@ func TestRepricingDynamicFee(t *testing.T) {
|
||||||
txs = append(txs, dynamicFeeTx(2, 100000, big.NewInt(1), big.NewInt(1), keys[2]))
|
txs = append(txs, dynamicFeeTx(2, 100000, big.NewInt(1), big.NewInt(1), keys[2]))
|
||||||
txs = append(txs, dynamicFeeTx(3, 100000, big.NewInt(2), big.NewInt(2), keys[2]))
|
txs = append(txs, dynamicFeeTx(3, 100000, big.NewInt(2), big.NewInt(2), keys[2]))
|
||||||
|
|
||||||
ltx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[3])
|
|
||||||
|
|
||||||
// Import the batch and that both pending and queued transactions match up
|
// Import the batch and that both pending and queued transactions match up
|
||||||
pool.addRemotesSync(txs)
|
pool.addRemotesSync(txs)
|
||||||
pool.addLocal(ltx)
|
|
||||||
|
|
||||||
pending, queued := pool.Stats()
|
pending, queued := pool.Stats()
|
||||||
if pending != 7 {
|
if pending != 6 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 7)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 6)
|
||||||
}
|
}
|
||||||
if queued != 3 {
|
if queued != 3 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
||||||
}
|
}
|
||||||
if err := validateEvents(events, 7); err != nil {
|
if err := validateEvents(events, 6); err != nil {
|
||||||
t.Fatalf("original event firing failed: %v", err)
|
t.Fatalf("original event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
|
@ -1595,8 +1484,8 @@ func TestRepricingDynamicFee(t *testing.T) {
|
||||||
pool.SetGasTip(big.NewInt(2))
|
pool.SetGasTip(big.NewInt(2))
|
||||||
|
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 1 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 1)
|
||||||
}
|
}
|
||||||
if queued != 5 {
|
if queued != 5 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 5)
|
||||||
|
@ -1626,20 +1515,7 @@ func TestRepricingDynamicFee(t *testing.T) {
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// However we can add local underpriced transactions
|
|
||||||
tx = dynamicFeeTx(1, 100000, big.NewInt(1), big.NewInt(1), keys[3])
|
|
||||||
if err := pool.addLocal(tx); err != nil {
|
|
||||||
t.Fatalf("failed to add underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if pending, _ = pool.Stats(); pending != 3 {
|
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 3)
|
|
||||||
}
|
|
||||||
if err := validateEvents(events, 1); err != nil {
|
|
||||||
t.Fatalf("post-reprice local event firing failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
// And we can fill gaps with properly priced transactions
|
// And we can fill gaps with properly priced transactions
|
||||||
tx = pricedTransaction(1, 100000, big.NewInt(2), keys[0])
|
tx = pricedTransaction(1, 100000, big.NewInt(2), keys[0])
|
||||||
if err := pool.addRemote(tx); err != nil {
|
if err := pool.addRemote(tx); err != nil {
|
||||||
|
@ -1661,77 +1537,6 @@ func TestRepricingDynamicFee(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that setting the transaction pool gas price to a higher value does not
|
|
||||||
// remove local transactions (legacy & dynamic fee).
|
|
||||||
func TestRepricingKeepsLocals(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Create the pool to test the pricing enforcement with
|
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
|
||||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
|
||||||
|
|
||||||
pool := New(testTxPoolConfig, blockchain)
|
|
||||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
|
||||||
defer pool.Close()
|
|
||||||
|
|
||||||
// Create a number of test accounts and fund them
|
|
||||||
keys := make([]*ecdsa.PrivateKey, 3)
|
|
||||||
for i := 0; i < len(keys); i++ {
|
|
||||||
keys[i], _ = crypto.GenerateKey()
|
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(100000*1000000))
|
|
||||||
}
|
|
||||||
// Create transaction (both pending and queued) with a linearly growing gasprice
|
|
||||||
for i := uint64(0); i < 500; i++ {
|
|
||||||
// Add pending transaction.
|
|
||||||
pendingTx := pricedTransaction(i, 100000, big.NewInt(int64(i)), keys[2])
|
|
||||||
if err := pool.addLocal(pendingTx); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// Add queued transaction.
|
|
||||||
queuedTx := pricedTransaction(i+501, 100000, big.NewInt(int64(i)), keys[2])
|
|
||||||
if err := pool.addLocal(queuedTx); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add pending dynamic fee transaction.
|
|
||||||
pendingTx = dynamicFeeTx(i, 100000, big.NewInt(int64(i)+1), big.NewInt(int64(i)), keys[1])
|
|
||||||
if err := pool.addLocal(pendingTx); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// Add queued dynamic fee transaction.
|
|
||||||
queuedTx = dynamicFeeTx(i+501, 100000, big.NewInt(int64(i)+1), big.NewInt(int64(i)), keys[1])
|
|
||||||
if err := pool.addLocal(queuedTx); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pending, queued := pool.Stats()
|
|
||||||
expPending, expQueued := 1000, 1000
|
|
||||||
validate := func() {
|
|
||||||
pending, queued = pool.Stats()
|
|
||||||
if pending != expPending {
|
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, expPending)
|
|
||||||
}
|
|
||||||
if queued != expQueued {
|
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validate()
|
|
||||||
|
|
||||||
// Reprice the pool and check that nothing is dropped
|
|
||||||
pool.SetGasTip(big.NewInt(2))
|
|
||||||
validate()
|
|
||||||
|
|
||||||
pool.SetGasTip(big.NewInt(2))
|
|
||||||
pool.SetGasTip(big.NewInt(4))
|
|
||||||
pool.SetGasTip(big.NewInt(8))
|
|
||||||
pool.SetGasTip(big.NewInt(100))
|
|
||||||
validate()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that when the pool reaches its global transaction limit, underpriced
|
// Tests that when the pool reaches its global transaction limit, underpriced
|
||||||
// transactions are gradually shifted out for more expensive ones and any gapped
|
// transactions are gradually shifted out for more expensive ones and any gapped
|
||||||
// pending transactions are moved into the queue.
|
// pending transactions are moved into the queue.
|
||||||
|
@ -1761,21 +1566,18 @@ func TestUnderpricing(t *testing.T) {
|
||||||
keys := make([]*ecdsa.PrivateKey, 5)
|
keys := make([]*ecdsa.PrivateKey, 5)
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
keys[i], _ = crypto.GenerateKey()
|
keys[i], _ = crypto.GenerateKey()
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000))
|
testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(10000000))
|
||||||
}
|
}
|
||||||
// Generate and queue a batch of transactions, both pending and queued
|
// Generate and queue a batch of transactions, both pending and queued
|
||||||
txs := types.Transactions{}
|
txs := types.Transactions{}
|
||||||
|
|
||||||
txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0]))
|
txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[0])) // pending
|
||||||
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0]))
|
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) // pending
|
||||||
|
txs = append(txs, pricedTransaction(0, 100000, big.NewInt(1), keys[2])) // pending
|
||||||
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1]))
|
|
||||||
|
|
||||||
ltx := pricedTransaction(0, 100000, big.NewInt(1), keys[2])
|
|
||||||
|
|
||||||
|
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(1), keys[1])) // queued
|
||||||
// Import the batch and that both pending and queued transactions match up
|
// Import the batch and that both pending and queued transactions match up
|
||||||
pool.addRemotes(txs)
|
pool.addRemotesSync(txs)
|
||||||
pool.addLocal(ltx)
|
|
||||||
|
|
||||||
pending, queued := pool.Stats()
|
pending, queued := pool.Stats()
|
||||||
if pending != 3 {
|
if pending != 3 {
|
||||||
|
@ -1805,48 +1607,26 @@ func TestUnderpricing(t *testing.T) {
|
||||||
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil { // +K1:2 => -K0:0 => Pend K1:0, K2:0; Que K0:1 K1:2
|
if err := pool.addRemoteSync(pricedTransaction(2, 100000, big.NewInt(4), keys[1])); err != nil { // +K1:2 => -K0:0 => Pend K1:0, K2:0; Que K0:1 K1:2
|
||||||
t.Fatalf("failed to add well priced transaction: %v", err)
|
t.Fatalf("failed to add well priced transaction: %v", err)
|
||||||
}
|
}
|
||||||
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
|
if err := pool.addRemoteSync(pricedTransaction(3, 100000, big.NewInt(5), keys[1])); err != nil { // +K1:3 => -K0:1 => Pend K1:0, K2:0; Que K1:2 K1:3
|
||||||
t.Fatalf("failed to add well priced transaction: %v", err)
|
t.Fatalf("failed to add well priced transaction: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that replacing a pending transaction with a future transaction fails
|
// Ensure that replacing a pending transaction with a future transaction fails
|
||||||
if err := pool.addRemote(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending {
|
if err := pool.addRemoteSync(pricedTransaction(5, 100000, big.NewInt(6), keys[1])); err != txpool.ErrFutureReplacePending {
|
||||||
t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending)
|
t.Fatalf("adding future replace transaction error mismatch: have %v, want %v", err, txpool.ErrFutureReplacePending)
|
||||||
}
|
}
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 4 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateEvents(events, 2); err != nil {
|
if err := validateEvents(events, 4); err != nil {
|
||||||
t.Fatalf("additional event firing failed: %v", err)
|
t.Fatalf("additional event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding local transactions can push out even higher priced ones
|
|
||||||
ltx = pricedTransaction(1, 100000, big.NewInt(0), keys[2])
|
|
||||||
if err := pool.addLocal(ltx); err != nil {
|
|
||||||
t.Fatalf("failed to append underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
ltx = pricedTransaction(0, 100000, big.NewInt(0), keys[3])
|
|
||||||
if err := pool.addLocal(ltx); err != nil {
|
|
||||||
t.Fatalf("failed to add new underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
pending, queued = pool.Stats()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if err := validateEvents(events, 2); err != nil {
|
|
||||||
t.Fatalf("local event firing failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that more expensive transactions push out cheap ones from the pool, but
|
// Tests that more expensive transactions push out cheap ones from the pool, but
|
||||||
|
@ -1920,8 +1700,6 @@ func TestStableUnderpricing(t *testing.T) {
|
||||||
// Tests that when the pool reaches its global transaction limit, underpriced
|
// Tests that when the pool reaches its global transaction limit, underpriced
|
||||||
// transactions (legacy & dynamic fee) are gradually shifted out for more
|
// transactions (legacy & dynamic fee) are gradually shifted out for more
|
||||||
// expensive ones and any gapped pending transactions are moved into the queue.
|
// expensive ones and any gapped pending transactions are moved into the queue.
|
||||||
//
|
|
||||||
// Note, local transactions are never allowed to be dropped.
|
|
||||||
func TestUnderpricingDynamicFee(t *testing.T) {
|
func TestUnderpricingDynamicFee(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -1946,15 +1724,13 @@ func TestUnderpricingDynamicFee(t *testing.T) {
|
||||||
// Generate and queue a batch of transactions, both pending and queued
|
// Generate and queue a batch of transactions, both pending and queued
|
||||||
txs := types.Transactions{}
|
txs := types.Transactions{}
|
||||||
|
|
||||||
txs = append(txs, dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[0]))
|
txs = append(txs, dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[0])) // pending
|
||||||
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0]))
|
txs = append(txs, pricedTransaction(1, 100000, big.NewInt(2), keys[0])) // pending
|
||||||
txs = append(txs, dynamicFeeTx(1, 100000, big.NewInt(2), big.NewInt(1), keys[1]))
|
txs = append(txs, dynamicFeeTx(1, 100000, big.NewInt(2), big.NewInt(1), keys[1])) // queued
|
||||||
|
txs = append(txs, dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[2])) // pending
|
||||||
|
|
||||||
ltx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[2])
|
// Import the batch and check that both pending and queued transactions match up
|
||||||
|
pool.addRemotesSync(txs) // Pend K0:0, K0:1; Que K1:1
|
||||||
// Import the batch and that both pending and queued transactions match up
|
|
||||||
pool.addRemotes(txs) // Pend K0:0, K0:1; Que K1:1
|
|
||||||
pool.addLocal(ltx) // +K2:0 => Pend K0:0, K0:1, K2:0; Que K1:1
|
|
||||||
|
|
||||||
pending, queued := pool.Stats()
|
pending, queued := pool.Stats()
|
||||||
if pending != 3 {
|
if pending != 3 {
|
||||||
|
@ -1972,13 +1748,13 @@ func TestUnderpricingDynamicFee(t *testing.T) {
|
||||||
|
|
||||||
// Ensure that adding an underpriced transaction fails
|
// Ensure that adding an underpriced transaction fails
|
||||||
tx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[1])
|
tx := dynamicFeeTx(0, 100000, big.NewInt(2), big.NewInt(1), keys[1])
|
||||||
if err := pool.addRemote(tx); !errors.Is(err, txpool.ErrUnderpriced) { // Pend K0:0, K0:1, K2:0; Que K1:1
|
if err := pool.addRemoteSync(tx); !errors.Is(err, txpool.ErrUnderpriced) { // Pend K0:0, K0:1, K2:0; Que K1:1
|
||||||
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced)
|
t.Fatalf("adding underpriced pending transaction error mismatch: have %v, want %v", err, txpool.ErrUnderpriced)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that adding high priced transactions drops cheap ones, but not own
|
// Ensure that adding high priced transactions drops cheap ones, but not own
|
||||||
tx = pricedTransaction(0, 100000, big.NewInt(2), keys[1])
|
tx = pricedTransaction(0, 100000, big.NewInt(2), keys[1])
|
||||||
if err := pool.addRemote(tx); err != nil { // +K1:0, -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que -
|
if err := pool.addRemoteSync(tx); err != nil { // +K1:0, -K1:1 => Pend K0:0, K0:1, K1:0, K2:0; Que -
|
||||||
t.Fatalf("failed to add well priced transaction: %v", err)
|
t.Fatalf("failed to add well priced transaction: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1991,40 +1767,18 @@ func TestUnderpricingDynamicFee(t *testing.T) {
|
||||||
t.Fatalf("failed to add well priced transaction: %v", err)
|
t.Fatalf("failed to add well priced transaction: %v", err)
|
||||||
}
|
}
|
||||||
pending, queued = pool.Stats()
|
pending, queued = pool.Stats()
|
||||||
if pending != 2 {
|
if pending != 4 {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 4)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 0 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0)
|
||||||
}
|
}
|
||||||
if err := validateEvents(events, 2); err != nil {
|
if err := validateEvents(events, 3); err != nil {
|
||||||
t.Fatalf("additional event firing failed: %v", err)
|
t.Fatalf("additional event firing failed: %v", err)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure that adding local transactions can push out even higher priced ones
|
|
||||||
ltx = dynamicFeeTx(1, 100000, big.NewInt(0), big.NewInt(0), keys[2])
|
|
||||||
if err := pool.addLocal(ltx); err != nil {
|
|
||||||
t.Fatalf("failed to append underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
ltx = dynamicFeeTx(0, 100000, big.NewInt(0), big.NewInt(0), keys[3])
|
|
||||||
if err := pool.addLocal(ltx); err != nil {
|
|
||||||
t.Fatalf("failed to add new underpriced local transaction: %v", err)
|
|
||||||
}
|
|
||||||
pending, queued = pool.Stats()
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if err := validateEvents(events, 2); err != nil {
|
|
||||||
t.Fatalf("local event firing failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests whether highest fee cap transaction is retained after a batch of high effective
|
// Tests whether highest fee cap transaction is retained after a batch of high effective
|
||||||
|
@ -2044,7 +1798,7 @@ func TestDualHeapEviction(t *testing.T) {
|
||||||
)
|
)
|
||||||
|
|
||||||
check := func(tx *types.Transaction, name string) {
|
check := func(tx *types.Transaction, name string) {
|
||||||
if pool.all.GetRemote(tx.Hash()) == nil {
|
if pool.all.Get(tx.Hash()) == nil {
|
||||||
t.Fatalf("highest %s transaction evicted from the pool", name)
|
t.Fatalf("highest %s transaction evicted from the pool", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2341,122 +2095,6 @@ func TestReplacementDynamicFee(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that local transactions are journaled to disk, but remote transactions
|
|
||||||
// get discarded between restarts.
|
|
||||||
func TestJournaling(t *testing.T) { testJournaling(t, false) }
|
|
||||||
func TestJournalingNoLocals(t *testing.T) { testJournaling(t, true) }
|
|
||||||
|
|
||||||
func testJournaling(t *testing.T, nolocals bool) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Create a temporary file for the journal
|
|
||||||
file, err := os.CreateTemp("", "")
|
|
||||||
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
|
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
|
||||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
|
||||||
|
|
||||||
config := testTxPoolConfig
|
|
||||||
config.NoLocals = nolocals
|
|
||||||
config.Journal = journal
|
|
||||||
config.Rejournal = time.Second
|
|
||||||
|
|
||||||
pool := New(config, blockchain)
|
|
||||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
|
||||||
|
|
||||||
// Create two test accounts to ensure remotes expire but locals do not
|
|
||||||
local, _ := crypto.GenerateKey()
|
|
||||||
remote, _ := crypto.GenerateKey()
|
|
||||||
|
|
||||||
testAddBalance(pool, crypto.PubkeyToAddress(local.PublicKey), big.NewInt(1000000000))
|
|
||||||
testAddBalance(pool, 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, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addLocal(pricedTransaction(1, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addLocal(pricedTransaction(2, 100000, big.NewInt(1), local)); err != nil {
|
|
||||||
t.Fatalf("failed to add local transaction: %v", err)
|
|
||||||
}
|
|
||||||
if err := pool.addRemoteSync(pricedTransaction(0, 100000, big.NewInt(1), remote)); err != nil {
|
|
||||||
t.Fatalf("failed to add remote transaction: %v", err)
|
|
||||||
}
|
|
||||||
pending, queued := pool.Stats()
|
|
||||||
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 := validatePoolInternals(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.Close()
|
|
||||||
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
|
|
||||||
blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
|
||||||
|
|
||||||
pool = New(config, blockchain)
|
|
||||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
|
||||||
|
|
||||||
pending, queued = pool.Stats()
|
|
||||||
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 := validatePoolInternals(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)
|
|
||||||
<-pool.requestReset(nil, nil)
|
|
||||||
time.Sleep(2 * config.Rejournal)
|
|
||||||
pool.Close()
|
|
||||||
|
|
||||||
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
|
|
||||||
blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
|
||||||
pool = New(config, blockchain)
|
|
||||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
|
||||||
|
|
||||||
pending, queued = pool.Stats()
|
|
||||||
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 := validatePoolInternals(pool); err != nil {
|
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
|
||||||
}
|
|
||||||
pool.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestStatusCheck tests that the pool can correctly retrieve the
|
// TestStatusCheck tests that the pool can correctly retrieve the
|
||||||
// pending status of individual transactions.
|
// pending status of individual transactions.
|
||||||
func TestStatusCheck(t *testing.T) {
|
func TestStatusCheck(t *testing.T) {
|
||||||
|
@ -2571,7 +2209,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
|
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
tx := transaction(uint64(1+i), 100000, key)
|
tx := transaction(uint64(1+i), 100000, key)
|
||||||
pool.enqueueTx(tx.Hash(), tx, false, true)
|
pool.enqueueTx(tx.Hash(), tx, true)
|
||||||
}
|
}
|
||||||
// Benchmark the speed of pool validation
|
// Benchmark the speed of pool validation
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
@ -2581,15 +2219,11 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmarks the speed of batched transaction insertion.
|
// Benchmarks the speed of batched transaction insertion.
|
||||||
func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, false) }
|
func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100) }
|
||||||
func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, false) }
|
func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000) }
|
||||||
func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, false) }
|
func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000) }
|
||||||
|
|
||||||
func BenchmarkBatchLocalInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, true) }
|
func benchmarkBatchInsert(b *testing.B, size int) {
|
||||||
func BenchmarkBatchLocalInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, true) }
|
|
||||||
func BenchmarkBatchLocalInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, true) }
|
|
||||||
|
|
||||||
func benchmarkBatchInsert(b *testing.B, size int, local bool) {
|
|
||||||
// Generate a batch of transactions to enqueue into the pool
|
// Generate a batch of transactions to enqueue into the pool
|
||||||
pool, key := setupPool()
|
pool, key := setupPool()
|
||||||
defer pool.Close()
|
defer pool.Close()
|
||||||
|
@ -2607,11 +2241,7 @@ func benchmarkBatchInsert(b *testing.B, size int, local bool) {
|
||||||
// Benchmark importing the transactions into the queue
|
// Benchmark importing the transactions into the queue
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for _, batch := range batches {
|
for _, batch := range batches {
|
||||||
if local {
|
pool.addRemotes(batch)
|
||||||
pool.addLocals(batch)
|
|
||||||
} else {
|
|
||||||
pool.addRemotes(batch)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2623,10 +2253,6 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
|
||||||
remoteKey, _ := crypto.GenerateKey()
|
remoteKey, _ := crypto.GenerateKey()
|
||||||
remoteAddr := crypto.PubkeyToAddress(remoteKey.PublicKey)
|
remoteAddr := crypto.PubkeyToAddress(remoteKey.PublicKey)
|
||||||
|
|
||||||
locals := make([]*types.Transaction, 4096+1024) // Occupy all slots
|
|
||||||
for i := 0; i < len(locals); i++ {
|
|
||||||
locals[i] = transaction(uint64(i), 100000, key)
|
|
||||||
}
|
|
||||||
remotes := make([]*types.Transaction, 1000)
|
remotes := make([]*types.Transaction, 1000)
|
||||||
for i := 0; i < len(remotes); i++ {
|
for i := 0; i < len(remotes); i++ {
|
||||||
remotes[i] = pricedTransaction(uint64(i), 100000, big.NewInt(2), remoteKey) // Higher gasprice
|
remotes[i] = pricedTransaction(uint64(i), 100000, big.NewInt(2), remoteKey) // Higher gasprice
|
||||||
|
@ -2637,9 +2263,6 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
pool, _ := setupPool()
|
pool, _ := setupPool()
|
||||||
testAddBalance(pool, account, big.NewInt(100000000))
|
testAddBalance(pool, account, big.NewInt(100000000))
|
||||||
for _, local := range locals {
|
|
||||||
pool.addLocal(local)
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
// Assign a high enough balance for testing
|
// Assign a high enough balance for testing
|
||||||
testAddBalance(pool, remoteAddr, big.NewInt(100000000))
|
testAddBalance(pool, remoteAddr, big.NewInt(100000000))
|
||||||
|
|
|
@ -590,7 +590,7 @@ func (l *pricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
|
||||||
// Discard stale price points if found at the heap start
|
// Discard stale price points if found at the heap start
|
||||||
for len(h.list) > 0 {
|
for len(h.list) > 0 {
|
||||||
head := h.list[0]
|
head := h.list[0]
|
||||||
if l.all.GetRemote(head.Hash()) == nil { // Removed or migrated
|
if l.all.Get(head.Hash()) == nil { // Removed or migrated
|
||||||
l.stales.Add(-1)
|
l.stales.Add(-1)
|
||||||
heap.Pop(h)
|
heap.Pop(h)
|
||||||
continue
|
continue
|
||||||
|
@ -615,7 +615,7 @@ func (l *pricedList) Discard(slots int) (types.Transactions, bool) {
|
||||||
if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio {
|
if len(l.urgent.list)*floatingRatio > len(l.floating.list)*urgentRatio {
|
||||||
// Discard stale transactions if found during cleanup
|
// Discard stale transactions if found during cleanup
|
||||||
tx := heap.Pop(&l.urgent).(*types.Transaction)
|
tx := heap.Pop(&l.urgent).(*types.Transaction)
|
||||||
if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
|
if l.all.Get(tx.Hash()) == nil { // Removed or migrated
|
||||||
l.stales.Add(-1)
|
l.stales.Add(-1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ func (l *pricedList) Discard(slots int) (types.Transactions, bool) {
|
||||||
}
|
}
|
||||||
// Discard stale transactions if found during cleanup
|
// Discard stale transactions if found during cleanup
|
||||||
tx := heap.Pop(&l.floating).(*types.Transaction)
|
tx := heap.Pop(&l.floating).(*types.Transaction)
|
||||||
if l.all.GetRemote(tx.Hash()) == nil { // Removed or migrated
|
if l.all.Get(tx.Hash()) == nil { // Removed or migrated
|
||||||
l.stales.Add(-1)
|
l.stales.Add(-1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -653,7 +653,7 @@ func (l *pricedList) Reheap() {
|
||||||
defer l.reheapMu.Unlock()
|
defer l.reheapMu.Unlock()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
l.stales.Store(0)
|
l.stales.Store(0)
|
||||||
l.urgent.list = make([]*types.Transaction, 0, l.all.RemoteCount())
|
l.urgent.list = make([]*types.Transaction, 0, l.all.Count())
|
||||||
l.all.Range(func(hash common.Hash, tx *types.Transaction) bool {
|
l.all.Range(func(hash common.Hash, tx *types.Transaction) bool {
|
||||||
l.urgent.list = append(l.urgent.list, tx)
|
l.urgent.list = append(l.urgent.list, tx)
|
||||||
return true
|
return true
|
||||||
|
|
Loading…
Reference in New Issue