mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-03 01:53:48 +00:00
core/types: fix transaction pool price-heap comparison (#33923)
Fixes priceheap comparison in some edge cases. --------- Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
This commit is contained in:
parent
2726c9ef9e
commit
1eead2ec33
2 changed files with 62 additions and 2 deletions
|
|
@ -68,6 +68,43 @@ func TestListAddVeryExpensive(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestPriceHeapCmp tests that the price heap comparison function works as intended.
|
||||
// It also tests combinations where the basefee is higher than the gas fee cap, which
|
||||
// are useful to sort in the mempool to support basefee changes.
|
||||
func TestPriceHeapCmp(t *testing.T) {
|
||||
key, _ := crypto.GenerateKey()
|
||||
txs := []*types.Transaction{
|
||||
// nonce, gaslimit, gasfee, gastip
|
||||
dynamicFeeTx(0, 1000, big.NewInt(2), big.NewInt(1), key),
|
||||
dynamicFeeTx(0, 1000, big.NewInt(1), big.NewInt(2), key),
|
||||
dynamicFeeTx(0, 1000, big.NewInt(1), big.NewInt(1), key),
|
||||
dynamicFeeTx(0, 1000, big.NewInt(1), big.NewInt(0), key),
|
||||
}
|
||||
|
||||
// create priceHeap
|
||||
ph := &priceHeap{}
|
||||
|
||||
// now set the basefee on the heap
|
||||
for _, basefee := range []uint64{0, 1, 2, 3} {
|
||||
ph.baseFee = uint256.NewInt(basefee)
|
||||
|
||||
for i := 0; i < len(txs); i++ {
|
||||
for j := 0; j < len(txs); j++ {
|
||||
switch {
|
||||
case i == j:
|
||||
if c := ph.cmp(txs[i], txs[j]); c != 0 {
|
||||
t.Errorf("tx %d should be equal priority to tx %d with basefee %d (cmp=%d)", i, j, basefee, c)
|
||||
}
|
||||
case i < j:
|
||||
if c := ph.cmp(txs[i], txs[j]); c != 1 {
|
||||
t.Errorf("tx %d vs tx %d comparison inconsistent with basefee %d (cmp=%d)", i, j, basefee, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkListAdd(b *testing.B) {
|
||||
// Generate a list of transactions to insert
|
||||
key, _ := crypto.GenerateKey()
|
||||
|
|
|
|||
|
|
@ -396,14 +396,37 @@ func (tx *Transaction) calcEffectiveGasTip(dst *uint256.Int, baseFee *uint256.In
|
|||
return err
|
||||
}
|
||||
|
||||
// EffectiveGasTipValue returns the effective gasTip value for the given base fee,
|
||||
// even if it would be negative. This can be used for sorting purposes.
|
||||
func (tx *Transaction) EffectiveGasTipValue(baseFee *big.Int) *big.Int {
|
||||
// min(gasTipCap, gasFeeCap - baseFee)
|
||||
dst := new(big.Int)
|
||||
if baseFee == nil {
|
||||
dst.Set(tx.inner.gasTipCap())
|
||||
return dst
|
||||
}
|
||||
|
||||
dst.Sub(tx.inner.gasFeeCap(), baseFee) // gasFeeCap - baseFee
|
||||
gasTipCap := tx.inner.gasTipCap()
|
||||
if gasTipCap.Cmp(dst) < 0 { // gasTipCap < (gasFeeCap - baseFee)
|
||||
dst.Set(gasTipCap)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *uint256.Int) int {
|
||||
if baseFee == nil {
|
||||
return tx.GasTipCapCmp(other)
|
||||
}
|
||||
// Use more efficient internal method.
|
||||
txTip, otherTip := new(uint256.Int), new(uint256.Int)
|
||||
tx.calcEffectiveGasTip(txTip, baseFee)
|
||||
other.calcEffectiveGasTip(otherTip, baseFee)
|
||||
err1 := tx.calcEffectiveGasTip(txTip, baseFee)
|
||||
err2 := other.calcEffectiveGasTip(otherTip, baseFee)
|
||||
if err1 != nil || err2 != nil {
|
||||
// fall back to big int comparison in case of error
|
||||
base := baseFee.ToBig()
|
||||
return tx.EffectiveGasTipValue(base).Cmp(other.EffectiveGasTipValue(base))
|
||||
}
|
||||
return txTip.Cmp(otherTip)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue