|
|
|
@ -14,7 +14,7 @@ |
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
package core |
|
|
|
|
package txpool |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"crypto/ecdsa" |
|
|
|
@ -28,6 +28,7 @@ import ( |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
"github.com/ethereum/go-ethereum/core" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/rawdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/state" |
|
|
|
|
"github.com/ethereum/go-ethereum/core/types" |
|
|
|
@ -40,14 +41,14 @@ import ( |
|
|
|
|
var ( |
|
|
|
|
// testTxPoolConfig is a transaction pool configuration without stateful disk
|
|
|
|
|
// sideeffects used during testing.
|
|
|
|
|
testTxPoolConfig TxPoolConfig |
|
|
|
|
testTxPoolConfig Config |
|
|
|
|
|
|
|
|
|
// eip1559Config is a chain config with EIP-1559 enabled at block 0.
|
|
|
|
|
eip1559Config *params.ChainConfig |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
|
testTxPoolConfig = DefaultTxPoolConfig |
|
|
|
|
testTxPoolConfig = DefaultConfig |
|
|
|
|
testTxPoolConfig.Journal = "" |
|
|
|
|
|
|
|
|
|
cpy := *params.TestChainConfig |
|
|
|
@ -76,7 +77,7 @@ func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { |
|
|
|
|
return bc.statedb, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Subscription { |
|
|
|
|
func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { |
|
|
|
|
return bc.chainHeadFeed.Subscribe(ch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -112,11 +113,11 @@ func dynamicFeeTx(nonce uint64, gaslimit uint64, gasFee *big.Int, tip *big.Int, |
|
|
|
|
return tx |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func setupTxPool() (*TxPool, *ecdsa.PrivateKey) { |
|
|
|
|
return setupTxPoolWithConfig(params.TestChainConfig) |
|
|
|
|
func setupPool() (*TxPool, *ecdsa.PrivateKey) { |
|
|
|
|
return setupPoolWithConfig(params.TestChainConfig) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) { |
|
|
|
|
func setupPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateKey) { |
|
|
|
|
statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) |
|
|
|
|
blockchain := &testBlockChain{10000000, statedb, new(event.Feed)} |
|
|
|
|
|
|
|
|
@ -128,8 +129,8 @@ func setupTxPoolWithConfig(config *params.ChainConfig) (*TxPool, *ecdsa.PrivateK |
|
|
|
|
return pool, key |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// validateTxPoolInternals checks various consistency invariants within the pool.
|
|
|
|
|
func validateTxPoolInternals(pool *TxPool) error { |
|
|
|
|
// validatePoolInternals checks various consistency invariants within the pool.
|
|
|
|
|
func validatePoolInternals(pool *TxPool) error { |
|
|
|
|
pool.mu.RLock() |
|
|
|
|
defer pool.mu.RUnlock() |
|
|
|
|
|
|
|
|
@ -161,7 +162,7 @@ func validateTxPoolInternals(pool *TxPool) error { |
|
|
|
|
|
|
|
|
|
// validateEvents checks that the correct number of transaction addition events
|
|
|
|
|
// were fired on the pool's event feed.
|
|
|
|
|
func validateEvents(events chan NewTxsEvent, count int) error { |
|
|
|
|
func validateEvents(events chan core.NewTxsEvent, count int) error { |
|
|
|
|
var received []*types.Transaction |
|
|
|
|
|
|
|
|
|
for len(received) < count { |
|
|
|
@ -218,7 +219,7 @@ func (c *testChain) State() (*state.StateDB, error) { |
|
|
|
|
// 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 TestStateChangeDuringTransactionPoolReset(t *testing.T) { |
|
|
|
|
func TestStateChangeDuringReset(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
@ -275,28 +276,28 @@ func testSetNonce(pool *TxPool, addr common.Address, nonce uint64) { |
|
|
|
|
func TestInvalidTransactions(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
tx := transaction(0, 100, key) |
|
|
|
|
from, _ := deriveSender(tx) |
|
|
|
|
|
|
|
|
|
testAddBalance(pool, from, big.NewInt(1)) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, ErrInsufficientFunds) { |
|
|
|
|
t.Error("expected", ErrInsufficientFunds) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, core.ErrInsufficientFunds) { |
|
|
|
|
t.Error("expected", core.ErrInsufficientFunds) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
balance := new(big.Int).Add(tx.Value(), new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())) |
|
|
|
|
testAddBalance(pool, from, balance) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, ErrIntrinsicGas) { |
|
|
|
|
t.Error("expected", ErrIntrinsicGas, "got", err) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, core.ErrIntrinsicGas) { |
|
|
|
|
t.Error("expected", core.ErrIntrinsicGas, "got", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
testSetNonce(pool, from, 1) |
|
|
|
|
testAddBalance(pool, from, big.NewInt(0xffffffffffffff)) |
|
|
|
|
tx = transaction(0, 100000, key) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, ErrNonceTooLow) { |
|
|
|
|
t.Error("expected", ErrNonceTooLow) |
|
|
|
|
if err := pool.AddRemote(tx); !errors.Is(err, core.ErrNonceTooLow) { |
|
|
|
|
t.Error("expected", core.ErrNonceTooLow) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tx = transaction(1, 100000, key) |
|
|
|
@ -309,10 +310,10 @@ func TestInvalidTransactions(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionQueue(t *testing.T) { |
|
|
|
|
func TestQueue(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
tx := transaction(0, 100, key) |
|
|
|
@ -340,10 +341,10 @@ func TestTransactionQueue(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionQueue2(t *testing.T) { |
|
|
|
|
func TestQueue2(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
tx1 := transaction(0, 100, key) |
|
|
|
@ -366,10 +367,10 @@ func TestTransactionQueue2(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionNegativeValue(t *testing.T) { |
|
|
|
|
func TestNegativeValue(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), 100, big.NewInt(1), nil), types.HomesteadSigner{}, key) |
|
|
|
@ -380,43 +381,43 @@ func TestTransactionNegativeValue(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionTipAboveFeeCap(t *testing.T) { |
|
|
|
|
func TestTipAboveFeeCap(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, key := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
tx := dynamicFeeTx(0, 100, big.NewInt(1), big.NewInt(2), key) |
|
|
|
|
|
|
|
|
|
if err := pool.AddRemote(tx); err != ErrTipAboveFeeCap { |
|
|
|
|
t.Error("expected", ErrTipAboveFeeCap, "got", err) |
|
|
|
|
if err := pool.AddRemote(tx); err != core.ErrTipAboveFeeCap { |
|
|
|
|
t.Error("expected", core.ErrTipAboveFeeCap, "got", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionVeryHighValues(t *testing.T) { |
|
|
|
|
func TestVeryHighValues(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, key := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
veryBigNumber := big.NewInt(1) |
|
|
|
|
veryBigNumber.Lsh(veryBigNumber, 300) |
|
|
|
|
|
|
|
|
|
tx := dynamicFeeTx(0, 100, big.NewInt(1), veryBigNumber, key) |
|
|
|
|
if err := pool.AddRemote(tx); err != ErrTipVeryHigh { |
|
|
|
|
t.Error("expected", ErrTipVeryHigh, "got", err) |
|
|
|
|
if err := pool.AddRemote(tx); err != core.ErrTipVeryHigh { |
|
|
|
|
t.Error("expected", core.ErrTipVeryHigh, "got", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tx2 := dynamicFeeTx(0, 100, veryBigNumber, big.NewInt(1), key) |
|
|
|
|
if err := pool.AddRemote(tx2); err != ErrFeeCapVeryHigh { |
|
|
|
|
t.Error("expected", ErrFeeCapVeryHigh, "got", err) |
|
|
|
|
if err := pool.AddRemote(tx2); err != core.ErrFeeCapVeryHigh { |
|
|
|
|
t.Error("expected", core.ErrFeeCapVeryHigh, "got", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionChainFork(t *testing.T) { |
|
|
|
|
func TestChainFork(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
addr := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -442,10 +443,10 @@ func TestTransactionChainFork(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionDoubleNonce(t *testing.T) { |
|
|
|
|
func TestDoubleNonce(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
addr := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -493,10 +494,10 @@ func TestTransactionDoubleNonce(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionMissingNonce(t *testing.T) { |
|
|
|
|
func TestMissingNonce(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
addr := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -516,11 +517,11 @@ func TestTransactionMissingNonce(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestTransactionNonceRecovery(t *testing.T) { |
|
|
|
|
func TestNonceRecovery(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
const n = 10 |
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
addr := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -542,11 +543,11 @@ func TestTransactionNonceRecovery(t *testing.T) { |
|
|
|
|
|
|
|
|
|
// Tests that if an account runs out of funds, any pending and queued transactions
|
|
|
|
|
// are dropped.
|
|
|
|
|
func TestTransactionDropping(t *testing.T) { |
|
|
|
|
func TestDropping(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a test account and fund it
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -646,7 +647,7 @@ func TestTransactionDropping(t *testing.T) { |
|
|
|
|
// 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
|
|
|
|
|
// postponed back into the future queue to prevent broadcasting them.
|
|
|
|
|
func TestTransactionPostponing(t *testing.T) { |
|
|
|
|
func TestPostponing(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the postponing with
|
|
|
|
@ -759,18 +760,18 @@ func TestTransactionPostponing(t *testing.T) { |
|
|
|
|
// Tests that if the transaction pool has both executable and non-executable
|
|
|
|
|
// transactions from an origin account, filling the nonce gap moves all queued
|
|
|
|
|
// ones into the pending pool.
|
|
|
|
|
func TestTransactionGapFilling(t *testing.T) { |
|
|
|
|
func TestGapFilling(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a test account and fund it
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
|
testAddBalance(pool, account, big.NewInt(1000000)) |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) |
|
|
|
|
events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -789,7 +790,7 @@ func TestTransactionGapFilling(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Fill the nonce gap and ensure all transactions become pending
|
|
|
|
@ -806,18 +807,18 @@ func TestTransactionGapFilling(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 2); err != nil { |
|
|
|
|
t.Fatalf("gap-filling event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that if the transaction count belonging to a single account goes above
|
|
|
|
|
// some threshold, the higher transactions are dropped to prevent DOS attacks.
|
|
|
|
|
func TestTransactionQueueAccountLimiting(t *testing.T) { |
|
|
|
|
func TestQueueAccountLimiting(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a test account and fund it
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -851,14 +852,14 @@ func TestTransactionQueueAccountLimiting(t *testing.T) { |
|
|
|
|
//
|
|
|
|
|
// This logic should not hold for local transactions, unless the local tracking
|
|
|
|
|
// mechanism is disabled.
|
|
|
|
|
func TestTransactionQueueGlobalLimiting(t *testing.T) { |
|
|
|
|
testTransactionQueueGlobalLimiting(t, false) |
|
|
|
|
func TestQueueGlobalLimiting(t *testing.T) { |
|
|
|
|
testQueueGlobalLimiting(t, false) |
|
|
|
|
} |
|
|
|
|
func TestTransactionQueueGlobalLimitingNoLocals(t *testing.T) { |
|
|
|
|
testTransactionQueueGlobalLimiting(t, true) |
|
|
|
|
func TestQueueGlobalLimitingNoLocals(t *testing.T) { |
|
|
|
|
testQueueGlobalLimiting(t, true) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
func testQueueGlobalLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the limit enforcement with
|
|
|
|
@ -941,14 +942,14 @@ func testTransactionQueueGlobalLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
//
|
|
|
|
|
// This logic should not hold for local transactions, unless the local tracking
|
|
|
|
|
// mechanism is disabled.
|
|
|
|
|
func TestTransactionQueueTimeLimiting(t *testing.T) { |
|
|
|
|
testTransactionQueueTimeLimiting(t, false) |
|
|
|
|
func TestQueueTimeLimiting(t *testing.T) { |
|
|
|
|
testQueueTimeLimiting(t, false) |
|
|
|
|
} |
|
|
|
|
func TestTransactionQueueTimeLimitingNoLocals(t *testing.T) { |
|
|
|
|
testTransactionQueueTimeLimiting(t, true) |
|
|
|
|
func TestQueueTimeLimitingNoLocals(t *testing.T) { |
|
|
|
|
testQueueTimeLimiting(t, true) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
func testQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
// Reduce the eviction interval to a testable amount
|
|
|
|
|
defer func(old time.Duration) { evictionInterval = old }(evictionInterval) |
|
|
|
|
evictionInterval = time.Millisecond * 100 |
|
|
|
@ -985,7 +986,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
if queued != 2 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1000,7 +1001,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
if queued != 2 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1020,7 +1021,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1037,7 +1038,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
if queued != 0 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1067,7 +1068,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
if queued != 2 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1086,7 +1087,7 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1094,18 +1095,18 @@ func testTransactionQueueTimeLimiting(t *testing.T, nolocals bool) { |
|
|
|
|
// 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) { |
|
|
|
|
func TestPendingLimiting(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a test account and fund it
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
|
testAddBalance(pool, account, big.NewInt(1000000)) |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, testTxPoolConfig.AccountQueue+5) |
|
|
|
|
events := make(chan core.NewTxsEvent, testTxPoolConfig.AccountQueue+5) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1127,7 +1128,7 @@ func TestTransactionPendingLimiting(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, int(testTxPoolConfig.AccountQueue+5)); err != nil { |
|
|
|
|
t.Fatalf("event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1135,7 +1136,7 @@ func TestTransactionPendingLimiting(t *testing.T) { |
|
|
|
|
// 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) { |
|
|
|
|
func TestPendingGlobalLimiting(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the limit enforcement with
|
|
|
|
@ -1175,7 +1176,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { |
|
|
|
|
if pending > int(config.GlobalSlots) { |
|
|
|
|
t.Fatalf("total pending transactions overflow allowance: %d > %d", pending, config.GlobalSlots) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1183,11 +1184,11 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) { |
|
|
|
|
// Test the limit on transaction size is enforced correctly.
|
|
|
|
|
// This test verifies every transaction having allowed size
|
|
|
|
|
// is added to the pool, and longer transactions are rejected.
|
|
|
|
|
func TestTransactionAllowedTxSize(t *testing.T) { |
|
|
|
|
func TestAllowedTxSize(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a test account and fund it
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -1231,13 +1232,13 @@ func TestTransactionAllowedTxSize(t *testing.T) { |
|
|
|
|
if queued != 0 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that if transactions start being capped, transactions are also removed from 'all'
|
|
|
|
|
func TestTransactionCapClearsFromAll(t *testing.T) { |
|
|
|
|
func TestCapClearsFromAll(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the limit enforcement with
|
|
|
|
@ -1263,7 +1264,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
// Import the batch and verify that limits have been enforced
|
|
|
|
|
pool.AddRemotes(txs) |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1271,7 +1272,7 @@ func TestTransactionCapClearsFromAll(t *testing.T) { |
|
|
|
|
// 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) { |
|
|
|
|
func TestPendingMinimumAllowance(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the limit enforcement with
|
|
|
|
@ -1309,7 +1310,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) { |
|
|
|
|
t.Errorf("addr %x: total pending transactions mismatch: have %d, want %d", addr, list.Len(), config.AccountSlots) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1319,7 +1320,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) { |
|
|
|
|
// from the pending pool to the queue.
|
|
|
|
|
//
|
|
|
|
|
// Note, local transactions are never allowed to be dropped.
|
|
|
|
|
func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
func TestRepricing(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -1330,7 +1331,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1371,7 +1372,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 7); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Reprice the pool and check that underpriced transactions get dropped
|
|
|
|
@ -1387,7 +1388,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 0); err != nil { |
|
|
|
|
t.Fatalf("reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Check that we can't add the old transactions back
|
|
|
|
@ -1403,7 +1404,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 0); err != nil { |
|
|
|
|
t.Fatalf("post-reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// However we can add local underpriced transactions
|
|
|
|
@ -1417,7 +1418,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("post-reprice local event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// And we can fill gaps with properly priced transactions
|
|
|
|
@ -1433,7 +1434,7 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 5); err != nil { |
|
|
|
|
t.Fatalf("post-reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1443,15 +1444,15 @@ func TestTransactionPoolRepricing(t *testing.T) { |
|
|
|
|
// gapped transactions back from the pending pool to the queue.
|
|
|
|
|
//
|
|
|
|
|
// Note, local transactions are never allowed to be dropped.
|
|
|
|
|
func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
func TestRepricingDynamicFee(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
|
pool, _ := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, _ := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1492,7 +1493,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 7); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Reprice the pool and check that underpriced transactions get dropped
|
|
|
|
@ -1508,7 +1509,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 0); err != nil { |
|
|
|
|
t.Fatalf("reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Check that we can't add the old transactions back
|
|
|
|
@ -1527,7 +1528,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 0); err != nil { |
|
|
|
|
t.Fatalf("post-reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// However we can add local underpriced transactions
|
|
|
|
@ -1541,7 +1542,7 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("post-reprice local event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// And we can fill gaps with properly priced transactions
|
|
|
|
@ -1560,14 +1561,14 @@ func TestTransactionPoolRepricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 5); err != nil { |
|
|
|
|
t.Fatalf("post-reprice event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that setting the transaction pool gas price to a higher value does not
|
|
|
|
|
// remove local transactions (legacy & dynamic fee).
|
|
|
|
|
func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { |
|
|
|
|
func TestRepricingKeepsLocals(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -1618,7 +1619,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, expQueued) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1640,7 +1641,7 @@ func TestTransactionPoolRepricingKeepsLocals(t *testing.T) { |
|
|
|
|
// pending transactions are moved into the queue.
|
|
|
|
|
//
|
|
|
|
|
// Note, local transactions are never allowed to be dropped.
|
|
|
|
|
func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
func TestUnderpricing(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -1655,7 +1656,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1689,7 +1690,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 3); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Ensure that adding an underpriced transaction on block limit fails
|
|
|
|
@ -1716,7 +1717,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("additional event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Ensure that adding local transactions can push out even higher priced ones
|
|
|
|
@ -1738,7 +1739,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 2); err != nil { |
|
|
|
|
t.Fatalf("local event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1746,7 +1747,7 @@ func TestTransactionPoolUnderpricing(t *testing.T) { |
|
|
|
|
// Tests that more expensive transactions push out cheap ones from the pool, but
|
|
|
|
|
// without producing instability by creating gaps that start jumping transactions
|
|
|
|
|
// back and forth between queued/pending.
|
|
|
|
|
func TestTransactionPoolStableUnderpricing(t *testing.T) { |
|
|
|
|
func TestStableUnderpricing(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -1761,7 +1762,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) { |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1788,7 +1789,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, int(config.GlobalSlots)); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Ensure that adding high priced transactions drops a cheap, but doesn't produce a gap
|
|
|
|
@ -1805,7 +1806,7 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("additional event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1815,17 +1816,17 @@ func TestTransactionPoolStableUnderpricing(t *testing.T) { |
|
|
|
|
// expensive ones and any gapped pending transactions are moved into the queue.
|
|
|
|
|
//
|
|
|
|
|
// Note, local transactions are never allowed to be dropped.
|
|
|
|
|
func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
func TestUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, _ := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, _ := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
pool.config.GlobalSlots = 2 |
|
|
|
|
pool.config.GlobalQueue = 2 |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -1859,7 +1860,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 3); err != nil { |
|
|
|
|
t.Fatalf("original event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1893,7 +1894,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 1); err != nil { |
|
|
|
|
t.Fatalf("additional event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Ensure that adding local transactions can push out even higher priced ones
|
|
|
|
@ -1915,7 +1916,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 2); err != nil { |
|
|
|
|
t.Fatalf("local event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1925,7 +1926,7 @@ func TestTransactionPoolUnderpricingDynamicFee(t *testing.T) { |
|
|
|
|
func TestDualHeapEviction(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
pool, _ := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, _ := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
pool.config.GlobalSlots = 10 |
|
|
|
@ -1972,13 +1973,13 @@ func TestDualHeapEviction(t *testing.T) { |
|
|
|
|
check(highTip, "effective tip") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that the pool rejects duplicate transactions.
|
|
|
|
|
func TestTransactionDeduplication(t *testing.T) { |
|
|
|
|
func TestDeduplication(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -2037,14 +2038,14 @@ func TestTransactionDeduplication(t *testing.T) { |
|
|
|
|
if queued != 0 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that the pool rejects replacement transactions that don't meet the minimum
|
|
|
|
|
// price bump required.
|
|
|
|
|
func TestTransactionReplacement(t *testing.T) { |
|
|
|
|
func TestReplacement(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
@ -2055,7 +2056,7 @@ func TestTransactionReplacement(t *testing.T) { |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -2117,23 +2118,23 @@ func TestTransactionReplacement(t *testing.T) { |
|
|
|
|
if err := validateEvents(events, 0); err != nil { |
|
|
|
|
t.Fatalf("queued replacement event firing failed: %v", err) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that the pool rejects replacement dynamic fee transactions that don't
|
|
|
|
|
// meet the minimum price bump required.
|
|
|
|
|
func TestTransactionReplacementDynamicFee(t *testing.T) { |
|
|
|
|
func TestReplacementDynamicFee(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the pricing enforcement with
|
|
|
|
|
pool, key := setupTxPoolWithConfig(eip1559Config) |
|
|
|
|
pool, key := setupPoolWithConfig(eip1559Config) |
|
|
|
|
defer pool.Stop() |
|
|
|
|
testAddBalance(pool, crypto.PubkeyToAddress(key.PublicKey), big.NewInt(1000000000)) |
|
|
|
|
|
|
|
|
|
// Keep track of transaction events to ensure all executables get announced
|
|
|
|
|
events := make(chan NewTxsEvent, 32) |
|
|
|
|
events := make(chan core.NewTxsEvent, 32) |
|
|
|
|
sub := pool.txFeed.Subscribe(events) |
|
|
|
|
defer sub.Unsubscribe() |
|
|
|
|
|
|
|
|
@ -2227,17 +2228,17 @@ func TestTransactionReplacementDynamicFee(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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 TestJournaling(t *testing.T) { testJournaling(t, false) } |
|
|
|
|
func TestJournalingNoLocals(t *testing.T) { testJournaling(t, true) } |
|
|
|
|
|
|
|
|
|
func testTransactionJournaling(t *testing.T, nolocals bool) { |
|
|
|
|
func testJournaling(t *testing.T, nolocals bool) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create a temporary file for the journal
|
|
|
|
@ -2290,7 +2291,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { |
|
|
|
|
if queued != 0 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 0) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
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
|
|
|
|
@ -2313,7 +2314,7 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { |
|
|
|
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
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
|
|
|
|
@ -2339,15 +2340,15 @@ func testTransactionJournaling(t *testing.T, nolocals bool) { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
pool.Stop() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TestTransactionStatusCheck tests that the pool can correctly retrieve the
|
|
|
|
|
// TestStatusCheck tests that the pool can correctly retrieve the
|
|
|
|
|
// pending status of individual transactions.
|
|
|
|
|
func TestTransactionStatusCheck(t *testing.T) { |
|
|
|
|
func TestStatusCheck(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
// Create the pool to test the status retrievals with
|
|
|
|
@ -2381,7 +2382,7 @@ func TestTransactionStatusCheck(t *testing.T) { |
|
|
|
|
if queued != 2 { |
|
|
|
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2) |
|
|
|
|
} |
|
|
|
|
if err := validateTxPoolInternals(pool); err != nil { |
|
|
|
|
if err := validatePoolInternals(pool); err != nil { |
|
|
|
|
t.Fatalf("pool internal state corrupted: %v", err) |
|
|
|
|
} |
|
|
|
|
// Retrieve the status of each transaction and validate them
|
|
|
|
@ -2402,7 +2403,7 @@ func TestTransactionStatusCheck(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test the transaction slots consumption is computed correctly
|
|
|
|
|
func TestTransactionSlotCount(t *testing.T) { |
|
|
|
|
func TestSlotCount(t *testing.T) { |
|
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
|
|
key, _ := crypto.GenerateKey() |
|
|
|
@ -2427,7 +2428,7 @@ func BenchmarkPendingDemotion10000(b *testing.B) { benchmarkPendingDemotion(b, 1 |
|
|
|
|
|
|
|
|
|
func benchmarkPendingDemotion(b *testing.B, size int) { |
|
|
|
|
// Add a batch of transactions to a pool one by one
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -2452,7 +2453,7 @@ func BenchmarkFuturePromotion10000(b *testing.B) { benchmarkFuturePromotion(b, 1 |
|
|
|
|
|
|
|
|
|
func benchmarkFuturePromotion(b *testing.B, size int) { |
|
|
|
|
// Add a batch of transactions to a pool one by one
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -2470,17 +2471,17 @@ func benchmarkFuturePromotion(b *testing.B, size int) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Benchmarks the speed of batched transaction insertion.
|
|
|
|
|
func BenchmarkPoolBatchInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, false) } |
|
|
|
|
func BenchmarkPoolBatchInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, false) } |
|
|
|
|
func BenchmarkPoolBatchInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, false) } |
|
|
|
|
func BenchmarkBatchInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, false) } |
|
|
|
|
func BenchmarkBatchInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, false) } |
|
|
|
|
func BenchmarkBatchInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, false) } |
|
|
|
|
|
|
|
|
|
func BenchmarkPoolBatchLocalInsert100(b *testing.B) { benchmarkPoolBatchInsert(b, 100, true) } |
|
|
|
|
func BenchmarkPoolBatchLocalInsert1000(b *testing.B) { benchmarkPoolBatchInsert(b, 1000, true) } |
|
|
|
|
func BenchmarkPoolBatchLocalInsert10000(b *testing.B) { benchmarkPoolBatchInsert(b, 10000, true) } |
|
|
|
|
func BenchmarkBatchLocalInsert100(b *testing.B) { benchmarkBatchInsert(b, 100, true) } |
|
|
|
|
func BenchmarkBatchLocalInsert1000(b *testing.B) { benchmarkBatchInsert(b, 1000, true) } |
|
|
|
|
func BenchmarkBatchLocalInsert10000(b *testing.B) { benchmarkBatchInsert(b, 10000, true) } |
|
|
|
|
|
|
|
|
|
func benchmarkPoolBatchInsert(b *testing.B, size int, local bool) { |
|
|
|
|
func benchmarkBatchInsert(b *testing.B, size int, local bool) { |
|
|
|
|
// Generate a batch of transactions to enqueue into the pool
|
|
|
|
|
pool, key := setupTxPool() |
|
|
|
|
pool, key := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
|
|
|
|
|
account := crypto.PubkeyToAddress(key.PublicKey) |
|
|
|
@ -2524,7 +2525,7 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) { |
|
|
|
|
b.ResetTimer() |
|
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
|
b.StopTimer() |
|
|
|
|
pool, _ := setupTxPool() |
|
|
|
|
pool, _ := setupPool() |
|
|
|
|
testAddBalance(pool, account, big.NewInt(100000000)) |
|
|
|
|
for _, local := range locals { |
|
|
|
|
pool.AddLocal(local) |
|
|
|
@ -2540,9 +2541,9 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Benchmarks the speed of batch transaction insertion in case of multiple accounts.
|
|
|
|
|
func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) { |
|
|
|
|
func BenchmarkMultiAccountBatchInsert(b *testing.B) { |
|
|
|
|
// Generate a batch of transactions to enqueue into the pool
|
|
|
|
|
pool, _ := setupTxPool() |
|
|
|
|
pool, _ := setupPool() |
|
|
|
|
defer pool.Stop() |
|
|
|
|
b.ReportAllocs() |
|
|
|
|
batches := make(types.Transactions, b.N) |