Skip to content

Commit

Permalink
Fix underpriced check for multi currency
Browse files Browse the repository at this point in the history
  • Loading branch information
hbandura committed Nov 24, 2023
1 parent 798a744 commit f3eb744
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
11 changes: 6 additions & 5 deletions core/tx_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,18 +696,19 @@ func (l *txPricedList) Underpriced(tx *types.Transaction) bool {
}

func (l *txPricedList) underpricedForMulti(h *multiCurrencyPriceHeap, tx *types.Transaction) bool {
underpriced := l.underpricedFor(h.nativeCurrencyHeap, tx)
// Has to be underpriced for ALL heaps to be underpriced for the whole pool.
underpriced := l.underpricedFor(h.nativeCurrencyHeap, tx, h.IsCheaper)
for _, sh := range h.currencyHeaps {
if l.underpricedFor(sh, tx) {
underpriced = true
if !l.underpricedFor(sh, tx, h.IsCheaper) {
underpriced = false
}
}
return underpriced
}

// underpricedFor checks whether a transaction is cheaper than (or as cheap as) the
// lowest priced (remote) transaction in the given heap.
func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool {
func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction, isCheaper func(tx1, tx2 *types.Transaction) bool) bool {
// Discard stale price points if found at the heap start
for len(h.list) > 0 {
head := h.list[0]
Expand All @@ -724,7 +725,7 @@ func (l *txPricedList) underpricedFor(h *priceHeap, tx *types.Transaction) bool
}
// If the remote transaction is even cheaper than the
// cheapest one tracked locally, reject it.
return h.cmp(h.list[0], tx) >= 0
return isCheaper(tx, h.list[0])
}

// Discard finds a number of most underpriced transactions, removes them from the
Expand Down
47 changes: 43 additions & 4 deletions core/tx_multicurrency_priceheap.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,39 @@ import (

type CurrencyCmpFn func(*big.Int, *common.Address, *big.Int, *common.Address) int

// IsCheaper returns true if tx1 is cheaper than tx2 (GasPrice with currency comparison)
// IsCheaper returns true if tx1 is cheaper (or equal) than tx2 (GasPrice with currency comparison)
func (cc CurrencyCmpFn) IsCheaper(tx1, tx2 *types.Transaction) bool {
return cc(tx1.GasPrice(), tx1.FeeCurrency(), tx2.GasPrice(), tx2.FeeCurrency()) < 0
return cc.Cmp(tx1, tx2, nil, nil) <= 0
}

func (cc CurrencyCmpFn) GasTipCapCmp(tx, other *types.Transaction) int {
return cc(tx.GasTipCap(), tx.FeeCurrency(), other.GasTipCap(), other.FeeCurrency())
}

func (cc CurrencyCmpFn) EffectiveGasTipCmp(tx, other *types.Transaction, baseFeeA, baseFeeB *big.Int) int {
if baseFeeA == nil && baseFeeB == nil {
return cc.GasTipCapCmp(tx, other)
}
return cc(tx.EffectiveGasTipValue(baseFeeA), tx.FeeCurrency(), other.EffectiveGasTipValue(baseFeeB), other.FeeCurrency())
}

func (cc CurrencyCmpFn) GasFeeCapCmp(a, b *types.Transaction) int {
return cc(a.GasFeeCap(), a.FeeCurrency(), b.GasFeeCap(), b.FeeCurrency())
}

func (cc CurrencyCmpFn) Cmp(a, b *types.Transaction, baseFeeA, baseFeeB *big.Int) int {
if baseFeeA != nil || baseFeeB != nil {
// Compare effective tips if baseFee is specified
if c := cc.EffectiveGasTipCmp(a, b, baseFeeA, baseFeeB); c != 0 {
return c
}
}
// Compare fee caps if baseFee is not specified or effective tips are equal
if c := cc.GasFeeCapCmp(a, b); c != 0 {
return c
}
// Compare tips if effective tips and fee caps are equal
return cc.GasTipCapCmp(a, b)
}

// multiCurrencyPriceHeap is a heap.Interface implementation over transactions
Expand All @@ -34,8 +64,10 @@ func newMultiCurrencyPriceHeap(currencyCmp CurrencyCmpFn, gpm GasPriceMinimums)

// inner state

nativeCurrencyHeap: &priceHeap{},
currencyHeaps: make(map[common.Address]*priceHeap),
nativeCurrencyHeap: &priceHeap{
baseFee: gpm.GetNativeGPM(),
},
currencyHeaps: make(map[common.Address]*priceHeap),
}
}

Expand Down Expand Up @@ -79,6 +111,13 @@ func (h *multiCurrencyPriceHeap) cheapestTxs() []*types.Transaction {
return txs
}

// IsCheaper returs true iff tx1 effective gas price <= tx2's
func (h *multiCurrencyPriceHeap) IsCheaper(tx1, tx2 *types.Transaction) bool {
baseFee1 := h.getHeapFor(tx1).baseFee
baseFee2 := h.getHeapFor(tx2).baseFee
return h.currencyCmp.Cmp(tx1, tx2, baseFee1, baseFee2) <= 0
}

func (h *multiCurrencyPriceHeap) cheapestTx() *types.Transaction {
txs := h.cheapestTxs()
var cheapestTx *types.Transaction
Expand Down

0 comments on commit f3eb744

Please sign in to comment.