core/txpool/legacypool: use uint256.Int instead of big.Int (#28606)
This change makes the legacy transaction pool use of `uint256.Int` instead of `big.Int`. The changes are made primarily only on the internal functions of legacypool. --------- Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
parent
f1c27c286e
commit
beb2954fa4
@ -342,7 +342,7 @@ func (p *BlobPool) Filter(tx *types.Transaction) bool {
|
||||
// Init sets the gas price needed to keep a transaction in the pool and the chain
|
||||
// head to allow balance / nonce checks. The transaction journal will be loaded
|
||||
// from disk and filtered based on the provided starting settings.
|
||||
func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.AddressReserver) error {
|
||||
func (p *BlobPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error {
|
||||
p.reserve = reserve
|
||||
|
||||
var (
|
||||
@ -420,7 +420,7 @@ func (p *BlobPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Addr
|
||||
basefeeGauge.Update(int64(basefee.Uint64()))
|
||||
blobfeeGauge.Update(int64(blobfee.Uint64()))
|
||||
|
||||
p.SetGasTip(gasTip)
|
||||
p.SetGasTip(new(big.Int).SetUint64(gasTip))
|
||||
|
||||
// Since the user might have modified their pool's capacity, evict anything
|
||||
// above the current allowance
|
||||
|
@ -567,7 +567,7 @@ func TestOpenDrops(t *testing.T) {
|
||||
statedb: statedb,
|
||||
}
|
||||
pool := New(Config{Datadir: storage}, chain)
|
||||
if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
t.Fatalf("failed to create blob pool: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
@ -686,7 +686,7 @@ func TestOpenIndex(t *testing.T) {
|
||||
statedb: statedb,
|
||||
}
|
||||
pool := New(Config{Datadir: storage}, chain)
|
||||
if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
t.Fatalf("failed to create blob pool: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
@ -788,7 +788,7 @@ func TestOpenHeap(t *testing.T) {
|
||||
statedb: statedb,
|
||||
}
|
||||
pool := New(Config{Datadir: storage}, chain)
|
||||
if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
t.Fatalf("failed to create blob pool: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
@ -868,7 +868,7 @@ func TestOpenCap(t *testing.T) {
|
||||
statedb: statedb,
|
||||
}
|
||||
pool := New(Config{Datadir: storage, Datacap: datacap}, chain)
|
||||
if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
t.Fatalf("failed to create blob pool: %v", err)
|
||||
}
|
||||
// Verify that enough transactions have been dropped to get the pool's size
|
||||
@ -1270,7 +1270,7 @@ func TestAdd(t *testing.T) {
|
||||
statedb: statedb,
|
||||
}
|
||||
pool := New(Config{Datadir: storage}, chain)
|
||||
if err := pool.Init(big.NewInt(1), chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(1, chain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
t.Fatalf("test %d: failed to create blob pool: %v", i, err)
|
||||
}
|
||||
verifyPoolInternals(t, pool)
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -202,7 +203,7 @@ type LegacyPool struct {
|
||||
config Config
|
||||
chainconfig *params.ChainConfig
|
||||
chain BlockChain
|
||||
gasTip atomic.Pointer[big.Int]
|
||||
gasTip atomic.Pointer[uint256.Int]
|
||||
txFeed event.Feed
|
||||
signer types.Signer
|
||||
mu sync.RWMutex
|
||||
@ -287,12 +288,12 @@ func (pool *LegacyPool) Filter(tx *types.Transaction) bool {
|
||||
// head to allow balance / nonce checks. The transaction journal will be loaded
|
||||
// from disk and filtered based on the provided starting settings. The internal
|
||||
// goroutines will be spun up and the pool deemed operational afterwards.
|
||||
func (pool *LegacyPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.AddressReserver) error {
|
||||
func (pool *LegacyPool) Init(gasTip uint64, head *types.Header, reserve txpool.AddressReserver) error {
|
||||
// Set the address reserver to request exclusive access to pooled accounts
|
||||
pool.reserve = reserve
|
||||
|
||||
// Set the basic pool parameters
|
||||
pool.gasTip.Store(gasTip)
|
||||
pool.gasTip.Store(uint256.NewInt(gasTip))
|
||||
|
||||
// Initialize the state with head block, or fallback to empty one in
|
||||
// case the head state is not available(might occur when node is not
|
||||
@ -433,11 +434,13 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
|
||||
pool.mu.Lock()
|
||||
defer pool.mu.Unlock()
|
||||
|
||||
old := pool.gasTip.Load()
|
||||
pool.gasTip.Store(new(big.Int).Set(tip))
|
||||
|
||||
var (
|
||||
newTip = uint256.MustFromBig(tip)
|
||||
old = pool.gasTip.Load()
|
||||
)
|
||||
pool.gasTip.Store(newTip)
|
||||
// If the min miner fee increased, remove transactions below the new threshold
|
||||
if tip.Cmp(old) > 0 {
|
||||
if newTip.Cmp(old) > 0 {
|
||||
// pool.priced is sorted by GasFeeCap, so we have to iterate through pool.all instead
|
||||
drop := pool.all.RemotesBelowTip(tip)
|
||||
for _, tx := range drop {
|
||||
@ -445,7 +448,7 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
|
||||
}
|
||||
pool.priced.Removed(len(drop))
|
||||
}
|
||||
log.Info("Legacy pool tip threshold updated", "tip", tip)
|
||||
log.Info("Legacy pool tip threshold updated", "tip", newTip)
|
||||
}
|
||||
|
||||
// Nonce returns the next nonce of an account, with all transactions executable
|
||||
@ -532,7 +535,7 @@ func (pool *LegacyPool) Pending(enforceTips bool) map[common.Address][]*txpool.L
|
||||
// If the miner requests tip enforcement, cap the lists now
|
||||
if enforceTips && !pool.locals.contains(addr) {
|
||||
for i, tx := range txs {
|
||||
if tx.EffectiveGasTipIntCmp(pool.gasTip.Load(), pool.priced.urgent.baseFee) < 0 {
|
||||
if tx.EffectiveGasTipIntCmp(pool.gasTip.Load().ToBig(), pool.priced.urgent.baseFee) < 0 {
|
||||
txs = txs[:i]
|
||||
break
|
||||
}
|
||||
@ -594,7 +597,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro
|
||||
1<<types.AccessListTxType |
|
||||
1<<types.DynamicFeeTxType,
|
||||
MaxSize: txMaxSize,
|
||||
MinTip: pool.gasTip.Load(),
|
||||
MinTip: pool.gasTip.Load().ToBig(),
|
||||
}
|
||||
if local {
|
||||
opts.MinTip = new(big.Int)
|
||||
@ -624,7 +627,7 @@ func (pool *LegacyPool) validateTx(tx *types.Transaction, local bool) error {
|
||||
},
|
||||
ExistingExpenditure: func(addr common.Address) *big.Int {
|
||||
if list := pool.pending[addr]; list != nil {
|
||||
return list.totalcost
|
||||
return list.totalcost.ToBig()
|
||||
}
|
||||
return new(big.Int)
|
||||
},
|
||||
@ -1441,7 +1444,7 @@ func (pool *LegacyPool) promoteExecutables(accounts []common.Address) []*types.T
|
||||
}
|
||||
log.Trace("Removed old queued transactions", "count", len(forwards))
|
||||
// Drop all transactions that are too costly (low balance or out of gas)
|
||||
drops, _ := list.Filter(pool.currentState.GetBalance(addr).ToBig(), gasLimit)
|
||||
drops, _ := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
|
||||
for _, tx := range drops {
|
||||
hash := tx.Hash()
|
||||
pool.all.Remove(hash)
|
||||
@ -1642,7 +1645,7 @@ func (pool *LegacyPool) demoteUnexecutables() {
|
||||
log.Trace("Removed old pending transaction", "hash", hash)
|
||||
}
|
||||
// Drop all transactions that are too costly (low balance or out of gas), and queue any invalids back for later
|
||||
drops, invalids := list.Filter(pool.currentState.GetBalance(addr).ToBig(), gasLimit)
|
||||
drops, invalids := list.Filter(pool.currentState.GetBalance(addr), gasLimit)
|
||||
for _, tx := range drops {
|
||||
hash := tx.Hash()
|
||||
log.Trace("Removed unpayable pending transaction", "hash", hash)
|
||||
|
@ -85,7 +85,7 @@ func TestTransactionFutureAttack(t *testing.T) {
|
||||
config.GlobalQueue = 100
|
||||
config.GlobalSlots = 100
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
fillPool(t, pool)
|
||||
pending, _ := pool.Stats()
|
||||
@ -119,7 +119,7 @@ func TestTransactionFuture1559(t *testing.T) {
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts, fund them and make transactions
|
||||
@ -152,7 +152,7 @@ func TestTransactionZAttack(t *testing.T) {
|
||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
// Create a number of test accounts, fund them and make transactions
|
||||
fillPool(t, pool)
|
||||
@ -223,7 +223,7 @@ func BenchmarkFutureAttack(b *testing.B) {
|
||||
config.GlobalQueue = 100
|
||||
config.GlobalSlots = 100
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
fillPool(b, pool)
|
||||
|
||||
|
@ -164,7 +164,7 @@ func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.Privat
|
||||
|
||||
key, _ := crypto.GenerateKey()
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
if err := pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
if err := pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// wait for the pool to initialize
|
||||
@ -199,9 +199,6 @@ func validatePoolInternals(pool *LegacyPool) error {
|
||||
if nonce := pool.pendingNonces.get(addr); nonce != last+1 {
|
||||
return fmt.Errorf("pending nonce mismatch: have %v, want %v", nonce, last+1)
|
||||
}
|
||||
if txs.totalcost.Cmp(common.Big0) < 0 {
|
||||
return fmt.Errorf("totalcost went negative: %v", txs.totalcost)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -283,7 +280,7 @@ func TestStateChangeDuringReset(t *testing.T) {
|
||||
tx1 := transaction(1, 100000, key)
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
nonce := pool.Nonce(address)
|
||||
@ -349,7 +346,7 @@ func TestInvalidTransactions(t *testing.T) {
|
||||
}
|
||||
|
||||
tx = transaction(1, 100000, key)
|
||||
pool.gasTip.Store(big.NewInt(1000))
|
||||
pool.gasTip.Store(uint256.NewInt(1000))
|
||||
if err, want := pool.addRemote(tx), txpool.ErrUnderpriced; !errors.Is(err, want) {
|
||||
t.Errorf("want %v have %v", want, err)
|
||||
}
|
||||
@ -703,7 +700,7 @@ func TestPostponing(t *testing.T) {
|
||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create two test accounts to produce different gap profiles with
|
||||
@ -920,7 +917,7 @@ func testQueueGlobalLimiting(t *testing.T, nolocals bool) {
|
||||
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.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts and fund them (last one will be the local)
|
||||
@ -1013,7 +1010,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||
config.NoLocals = nolocals
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create two test accounts to ensure remotes expire but locals do not
|
||||
@ -1198,7 +1195,7 @@ func TestPendingGlobalLimiting(t *testing.T) {
|
||||
config.GlobalSlots = config.AccountSlots * 10
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -1302,7 +1299,7 @@ func TestCapClearsFromAll(t *testing.T) {
|
||||
config.GlobalSlots = 8
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -1335,7 +1332,7 @@ func TestPendingMinimumAllowance(t *testing.T) {
|
||||
config.GlobalSlots = 1
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -1381,7 +1378,7 @@ func TestRepricing(t *testing.T) {
|
||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Keep track of transaction events to ensure all executables get announced
|
||||
@ -1503,7 +1500,7 @@ func TestMinGasPriceEnforced(t *testing.T) {
|
||||
txPoolConfig := DefaultConfig
|
||||
txPoolConfig.NoLocals = true
|
||||
pool := New(txPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(txPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(txPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
key, _ := crypto.GenerateKey()
|
||||
@ -1674,7 +1671,7 @@ func TestRepricingKeepsLocals(t *testing.T) {
|
||||
blockchain := newTestBlockChain(eip1559Config, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -1752,7 +1749,7 @@ func TestUnderpricing(t *testing.T) {
|
||||
config.GlobalQueue = 2
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Keep track of transaction events to ensure all executables get announced
|
||||
@ -1867,7 +1864,7 @@ func TestStableUnderpricing(t *testing.T) {
|
||||
config.GlobalQueue = 0
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Keep track of transaction events to ensure all executables get announced
|
||||
@ -2096,7 +2093,7 @@ func TestDeduplication(t *testing.T) {
|
||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create a test account to add transactions with
|
||||
@ -2163,7 +2160,7 @@ func TestReplacement(t *testing.T) {
|
||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Keep track of transaction events to ensure all executables get announced
|
||||
@ -2374,7 +2371,7 @@ func testJournaling(t *testing.T, nolocals bool) {
|
||||
config.Rejournal = time.Second
|
||||
|
||||
pool := New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
|
||||
// Create two test accounts to ensure remotes expire but locals do not
|
||||
local, _ := crypto.GenerateKey()
|
||||
@ -2412,7 +2409,7 @@ func testJournaling(t *testing.T, nolocals bool) {
|
||||
blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool = New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
|
||||
pending, queued = pool.Stats()
|
||||
if queued != 0 {
|
||||
@ -2439,7 +2436,7 @@ func testJournaling(t *testing.T, nolocals bool) {
|
||||
statedb.SetNonce(crypto.PubkeyToAddress(local.PublicKey), 1)
|
||||
blockchain = newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
pool = New(config, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(config.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(config.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
|
||||
pending, queued = pool.Stats()
|
||||
if pending != 0 {
|
||||
@ -2470,7 +2467,7 @@ func TestStatusCheck(t *testing.T) {
|
||||
blockchain := newTestBlockChain(params.TestChainConfig, 1000000, statedb, new(event.Feed))
|
||||
|
||||
pool := New(testTxPoolConfig, blockchain)
|
||||
pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver())
|
||||
pool.Init(testTxPoolConfig.PriceLimit, blockchain.CurrentBlock(), makeAddressReserver())
|
||||
defer pool.Close()
|
||||
|
||||
// Create the test accounts to check various transaction statuses with
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// nonceHeap is a heap.Interface implementation over 64bit unsigned integers for
|
||||
@ -271,9 +272,9 @@ type list struct {
|
||||
strict bool // Whether nonces are strictly continuous or not
|
||||
txs *sortedMap // Heap indexed sorted hash map of the transactions
|
||||
|
||||
costcap *big.Int // Price of the highest costing transaction (reset only if exceeds balance)
|
||||
costcap *uint256.Int // Price of the highest costing transaction (reset only if exceeds balance)
|
||||
gascap uint64 // Gas limit of the highest spending transaction (reset only if exceeds block limit)
|
||||
totalcost *big.Int // Total cost of all transactions in the list
|
||||
totalcost *uint256.Int // Total cost of all transactions in the list
|
||||
}
|
||||
|
||||
// newList create a new transaction list for maintaining nonce-indexable fast,
|
||||
@ -282,8 +283,8 @@ func newList(strict bool) *list {
|
||||
return &list{
|
||||
strict: strict,
|
||||
txs: newSortedMap(),
|
||||
costcap: new(big.Int),
|
||||
totalcost: new(big.Int),
|
||||
costcap: new(uint256.Int),
|
||||
totalcost: new(uint256.Int),
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,10 +326,15 @@ func (l *list) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transa
|
||||
l.subTotalCost([]*types.Transaction{old})
|
||||
}
|
||||
// Add new tx cost to totalcost
|
||||
l.totalcost.Add(l.totalcost, tx.Cost())
|
||||
cost, overflow := uint256.FromBig(tx.Cost())
|
||||
if overflow {
|
||||
return false, nil
|
||||
}
|
||||
l.totalcost.Add(l.totalcost, cost)
|
||||
|
||||
// Otherwise overwrite the old transaction with the current one
|
||||
l.txs.Put(tx)
|
||||
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
|
||||
if l.costcap.Cmp(cost) < 0 {
|
||||
l.costcap = cost
|
||||
}
|
||||
if gas := tx.Gas(); l.gascap < gas {
|
||||
@ -355,17 +361,17 @@ func (l *list) Forward(threshold uint64) types.Transactions {
|
||||
// a point in calculating all the costs or if the balance covers all. If the threshold
|
||||
// is lower than the costgas cap, the caps will be reset to a new high after removing
|
||||
// the newly invalidated transactions.
|
||||
func (l *list) Filter(costLimit *big.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
|
||||
func (l *list) Filter(costLimit *uint256.Int, gasLimit uint64) (types.Transactions, types.Transactions) {
|
||||
// If all transactions are below the threshold, short circuit
|
||||
if l.costcap.Cmp(costLimit) <= 0 && l.gascap <= gasLimit {
|
||||
return nil, nil
|
||||
}
|
||||
l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
|
||||
l.costcap = new(uint256.Int).Set(costLimit) // Lower the caps to the thresholds
|
||||
l.gascap = gasLimit
|
||||
|
||||
// Filter out all the transactions above the account's funds
|
||||
removed := l.txs.Filter(func(tx *types.Transaction) bool {
|
||||
return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit) > 0
|
||||
return tx.Gas() > gasLimit || tx.Cost().Cmp(costLimit.ToBig()) > 0
|
||||
})
|
||||
|
||||
if len(removed) == 0 {
|
||||
@ -456,7 +462,10 @@ func (l *list) LastElement() *types.Transaction {
|
||||
// total cost of all transactions.
|
||||
func (l *list) subTotalCost(txs []*types.Transaction) {
|
||||
for _, tx := range txs {
|
||||
l.totalcost.Sub(l.totalcost, tx.Cost())
|
||||
_, underflow := l.totalcost.SubOverflow(l.totalcost, uint256.MustFromBig(tx.Cost()))
|
||||
if underflow {
|
||||
panic("totalcost underflow")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,10 @@ import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// Tests that transactions can be added to strict lists and list contents and
|
||||
@ -51,6 +53,21 @@ func TestStrictListAdd(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestListAddVeryExpensive tests adding txs which exceed 256 bits in cost. It is
|
||||
// expected that the list does not panic.
|
||||
func TestListAddVeryExpensive(t *testing.T) {
|
||||
key, _ := crypto.GenerateKey()
|
||||
list := newList(true)
|
||||
for i := 0; i < 3; i++ {
|
||||
value := big.NewInt(100)
|
||||
gasprice, _ := new(big.Int).SetString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0)
|
||||
gaslimit := uint64(i)
|
||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), common.Address{}, value, gaslimit, gasprice, nil), types.HomesteadSigner{}, key)
|
||||
t.Logf("cost: %x bitlen: %d\n", tx.Cost(), tx.Cost().BitLen())
|
||||
list.Add(tx, DefaultConfig.PriceBump)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListAdd(b *testing.B) {
|
||||
// Generate a list of transactions to insert
|
||||
key, _ := crypto.GenerateKey()
|
||||
@ -60,7 +77,7 @@ func BenchmarkListAdd(b *testing.B) {
|
||||
txs[i] = transaction(uint64(i), 0, key)
|
||||
}
|
||||
// Insert the transactions in a random order
|
||||
priceLimit := big.NewInt(int64(DefaultConfig.PriceLimit))
|
||||
priceLimit := uint256.NewInt(DefaultConfig.PriceLimit)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
list := newList(true)
|
||||
|
@ -86,7 +86,7 @@ type SubPool interface {
|
||||
// These should not be passed as a constructor argument - nor should the pools
|
||||
// start by themselves - in order to keep multiple subpools in lockstep with
|
||||
// one another.
|
||||
Init(gasTip *big.Int, head *types.Header, reserve AddressReserver) error
|
||||
Init(gasTip uint64, head *types.Header, reserve AddressReserver) error
|
||||
|
||||
// Close terminates any background processing threads and releases any held
|
||||
// resources.
|
||||
|
@ -79,7 +79,7 @@ type TxPool struct {
|
||||
|
||||
// New creates a new transaction pool to gather, sort and filter inbound
|
||||
// transactions from the network.
|
||||
func New(gasTip *big.Int, chain BlockChain, subpools []SubPool) (*TxPool, error) {
|
||||
func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) {
|
||||
// Retrieve the current head so that all subpools and this main coordinator
|
||||
// pool will have the same starting state, even if the chain moves forward
|
||||
// during initialization.
|
||||
|
@ -229,7 +229,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
}
|
||||
legacyPool := legacypool.New(config.TxPool, eth.blockchain)
|
||||
|
||||
eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
|
||||
eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
|
||||
txconfig.Journal = "" // Don't litter the disk with test journals
|
||||
|
||||
pool := legacypool.New(txconfig, chain)
|
||||
txpool, _ := txpool.New(new(big.Int).SetUint64(txconfig.PriceLimit), chain, []txpool.SubPool{pool})
|
||||
txpool, _ := txpool.New(txconfig.PriceLimit, chain, []txpool.SubPool{pool})
|
||||
|
||||
return &testBackend{
|
||||
db: db,
|
||||
|
@ -317,7 +317,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) {
|
||||
blockchain := &testBlockChain{bc.Genesis().Root(), chainConfig, statedb, 10000000, new(event.Feed)}
|
||||
|
||||
pool := legacypool.New(testTxPoolConfig, blockchain)
|
||||
txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain, []txpool.SubPool{pool})
|
||||
txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, blockchain, []txpool.SubPool{pool})
|
||||
|
||||
backend := NewMockBackend(bc, txpool)
|
||||
// Create event Mux
|
||||
|
@ -135,7 +135,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
||||
t.Fatalf("core.NewBlockChain failed: %v", err)
|
||||
}
|
||||
pool := legacypool.New(testTxPoolConfig, chain)
|
||||
txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), chain, []txpool.SubPool{pool})
|
||||
txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, chain, []txpool.SubPool{pool})
|
||||
|
||||
return &testWorkerBackend{
|
||||
db: db,
|
||||
|
Loading…
Reference in New Issue
Block a user