Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core/txpool/legacypool: use uint256.Int instead of big.Int #28606

Merged
merged 6 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions common/big.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,13 @@ var (

U2560 = uint256.NewInt(0)
)

var (
Uint1 = uint256.NewInt(1)
Uint2 = uint256.NewInt(2)
Uint3 = uint256.NewInt(3)
Uint0 = uint256.NewInt(0)
Uint32 = uint256.NewInt(32)
Uint256 = uint256.NewInt(256)
Uint257 = uint256.NewInt(257)
)
19 changes: 10 additions & 9 deletions core/txpool/legacypool/legacypool.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -292,7 +293,7 @@ func (pool *LegacyPool) Init(gasTip *big.Int, head *types.Header, reserve txpool
pool.reserve = reserve

// Set the basic pool parameters
pool.gasTip.Store(gasTip)
pool.gasTip.Store(uint256.MustFromBig(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
Expand Down Expand Up @@ -434,10 +435,10 @@ func (pool *LegacyPool) SetGasTip(tip *big.Int) {
defer pool.mu.Unlock()

old := pool.gasTip.Load()
pool.gasTip.Store(new(big.Int).Set(tip))
pool.gasTip.Store(uint256.MustFromBig(tip))

// If the min miner fee increased, remove transactions below the new threshold
if tip.Cmp(old) > 0 {
if uint256.MustFromBig(tip).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 {
Expand Down Expand Up @@ -532,7 +533,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
}
Expand Down Expand Up @@ -594,7 +595,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(),
karalabe marked this conversation as resolved.
Show resolved Hide resolved
}
if local {
opts.MinTip = new(big.Int)
Expand Down Expand Up @@ -624,7 +625,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)
},
Expand Down Expand Up @@ -1441,7 +1442,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)
Expand Down Expand Up @@ -1642,7 +1643,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)
Expand Down
5 changes: 1 addition & 4 deletions core/txpool/legacypool/legacypool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
}
Expand Down
27 changes: 16 additions & 11 deletions core/txpool/legacypool/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
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
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 *uint256.Int // Total cost of all transactions in the list
}

// newList create a new transaction list for maintaining nonce-indexable fast,
Expand All @@ -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),
}
}

Expand Down Expand Up @@ -325,10 +326,11 @@ 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())
l.totalcost.Add(l.totalcost, uint256.MustFromBig(tx.Cost()))

// Otherwise overwrite the old transaction with the current one
l.txs.Put(tx)
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
if cost := uint256.MustFromBig(tx.Cost()); l.costcap.Cmp(cost) < 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Add function is a public function on the list. It should not panic, which it does if you use MustFromBig like this. I'm adding a testcase and a fix

l.costcap = cost
}
if gas := tx.Gas(); l.gascap < gas {
Expand All @@ -355,17 +357,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 {
Expand Down Expand Up @@ -456,7 +458,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")
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/txpool/legacypool/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
package legacypool

import (
"math/big"
"math/rand"
"testing"

"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
Expand Down Expand Up @@ -60,7 +60,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)
Expand Down