mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-18 22:09:26 +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) {
|
func BenchmarkListAdd(b *testing.B) {
|
||||||
// Generate a list of transactions to insert
|
// Generate a list of transactions to insert
|
||||||
key, _ := crypto.GenerateKey()
|
key, _ := crypto.GenerateKey()
|
||||||
|
|
|
||||||
|
|
@ -396,14 +396,37 @@ func (tx *Transaction) calcEffectiveGasTip(dst *uint256.Int, baseFee *uint256.In
|
||||||
return err
|
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 {
|
func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *uint256.Int) int {
|
||||||
if baseFee == nil {
|
if baseFee == nil {
|
||||||
return tx.GasTipCapCmp(other)
|
return tx.GasTipCapCmp(other)
|
||||||
}
|
}
|
||||||
// Use more efficient internal method.
|
// Use more efficient internal method.
|
||||||
txTip, otherTip := new(uint256.Int), new(uint256.Int)
|
txTip, otherTip := new(uint256.Int), new(uint256.Int)
|
||||||
tx.calcEffectiveGasTip(txTip, baseFee)
|
err1 := tx.calcEffectiveGasTip(txTip, baseFee)
|
||||||
other.calcEffectiveGasTip(otherTip, 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)
|
return txTip.Cmp(otherTip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue