From f3eb74449bcd1b4d2ed8b341de436ae071c92c82 Mon Sep 17 00:00:00 2001 From: Pasto Date: Fri, 24 Nov 2023 07:04:58 -0300 Subject: [PATCH] Fix underpriced check for multi currency --- core/tx_list.go | 11 +++---- core/tx_multicurrency_priceheap.go | 47 +++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/core/tx_list.go b/core/tx_list.go index ffb6734c76..f53a531dca 100644 --- a/core/tx_list.go +++ b/core/tx_list.go @@ -696,10 +696,11 @@ 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 @@ -707,7 +708,7 @@ func (l *txPricedList) underpricedForMulti(h *multiCurrencyPriceHeap, tx *types. // 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] @@ -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 diff --git a/core/tx_multicurrency_priceheap.go b/core/tx_multicurrency_priceheap.go index 0eac32bafb..21de571494 100644 --- a/core/tx_multicurrency_priceheap.go +++ b/core/tx_multicurrency_priceheap.go @@ -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 @@ -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), } } @@ -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