Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
37 changes: 37 additions & 0 deletions core/txpool/legacypool/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
27 changes: 25 additions & 2 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down