mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 15:47:21 +00:00
core/txpool/blobpool: adopt log calculation to new max decrease
EIP-7892 (BPO) changed the maximum blobfee decrease in a slot from 1.125 to 1.17 . Since we want priorties to approximate time, we should change our log calculation. Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
This commit is contained in:
parent
a19f1ff11b
commit
27994a7c09
6 changed files with 41 additions and 24 deletions
|
|
@ -171,7 +171,7 @@ func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transac
|
|||
blobGas: tx.BlobGas(),
|
||||
}
|
||||
meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap)
|
||||
meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap)
|
||||
meta.blobfeeJumps = dynamicBlobFeeJumps(meta.blobFeeCap)
|
||||
|
||||
return meta
|
||||
}
|
||||
|
|
@ -317,14 +317,20 @@ func newBlobTxMeta(id uint64, size uint64, storageSize uint32, tx *types.Transac
|
|||
// the current fee to the transaction's cap:
|
||||
//
|
||||
// jumps = floor(log1.125(txfee) - log1.125(basefee))
|
||||
|
||||
//
|
||||
// For blob fees, EIP-7892 changed the ratio of target to max blobs, and
|
||||
// with that also the maximum blob fee decrease in a slot from 1.125 to
|
||||
// approx 1.17. therefore, we use:
|
||||
//
|
||||
// blobfeeJumps = floor(log1.17(txBlobfee) - log1.17(blobfee))
|
||||
//
|
||||
// - The second observation is that when ranking executable blob txs, it
|
||||
// does not make sense to grant a later eviction priority to txs with high
|
||||
// fee caps since it could enable pool wars. As such, any positive priority
|
||||
// will be grouped together.
|
||||
//
|
||||
// priority = min(jumps, 0)
|
||||
|
||||
//
|
||||
// - The third observation is that the basefee and blobfee move independently,
|
||||
// so there's no way to split mixed txs on their own (A has higher base fee,
|
||||
// B has higher blob fee).
|
||||
|
|
|
|||
|
|
@ -830,8 +830,8 @@ func TestOpenIndex(t *testing.T) {
|
|||
//blobfeeJumps = []float64{34.023, 35.570, 36.879, 29.686, 26.243, 20.358} // log 1.125 (blob fee cap)
|
||||
|
||||
evictExecTipCaps = []uint64{10, 10, 5, 5, 1, 1}
|
||||
evictExecFeeJumps = []float64{39.098, 38.204, 38.204, 19.549, 19.549, 19.549} // min(log 1.125 (exec fee cap))
|
||||
evictBlobFeeJumps = []float64{34.023, 34.023, 34.023, 29.686, 26.243, 20.358} // min(log 1.125 (blob fee cap))
|
||||
evictExecFeeJumps = []float64{39.098, 38.204, 38.204, 19.549, 19.549, 19.549} // min(log 1.125 (exec fee cap))
|
||||
evictBlobFeeJumps = []float64{25.517256, 25.517256, 25.517256, 22.264502, 19.682646, 15.268934} // min(log 1.17 (blob fee cap))
|
||||
|
||||
totalSpent = uint256.NewInt(21000*(100+90+200+10+80+300) + blobSize*(55+66+77+33+22+11) + 100*6) // 21000 gas x price + 128KB x blobprice + value
|
||||
)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func newPriceHeap(basefee *uint256.Int, blobfee *uint256.Int, index map[common.A
|
|||
func (h *evictHeap) reinit(basefee *uint256.Int, blobfee *uint256.Int, force bool) {
|
||||
// If the update is mostly the same as the old, don't sort pointlessly
|
||||
basefeeJumps := dynamicFeeJumps(basefee)
|
||||
blobfeeJumps := dynamicFeeJumps(blobfee)
|
||||
blobfeeJumps := dynamicBlobFeeJumps(blobfee)
|
||||
|
||||
if !force && math.Abs(h.basefeeJumps-basefeeJumps) < 0.01 && math.Abs(h.blobfeeJumps-blobfeeJumps) < 0.01 { // TODO(karalabe): 0.01 enough, maybe should be smaller? Maybe this optimization is moot?
|
||||
return
|
||||
|
|
|
|||
|
|
@ -109,22 +109,22 @@ func TestPriceHeapSorting(t *testing.T) {
|
|||
order: []int{3, 2, 1, 0, 4, 5, 6},
|
||||
},
|
||||
// If both basefee and blobfee is specified, sort by the larger distance
|
||||
// of the two from the current network conditions, splitting same (loglog)
|
||||
// of the two from the current network conditions, splitting same
|
||||
// ones via the tip.
|
||||
//
|
||||
// Basefee: 1000
|
||||
// Blobfee: 100
|
||||
// Basefee: 1000 , jumps: 888, 790, 702, 624
|
||||
// Blobfee: 100 , jumps: 85, 73, 62, 53
|
||||
//
|
||||
// Tx #0: (800, 80) - 2 jumps below both => priority -1
|
||||
// Tx #1: (630, 63) - 4 jumps below both => priority -2
|
||||
// Tx #2: (800, 63) - 2 jumps below basefee, 4 jumps below blobfee => priority -2 (blob penalty dominates)
|
||||
// Tx #3: (630, 80) - 4 jumps below basefee, 2 jumps below blobfee => priority -2 (base penalty dominates)
|
||||
// Tx #0: (800, 80) - 2 jumps below both => priority -2
|
||||
// Tx #1: (630, 55) - 4 jumps below both => priority -4
|
||||
// Tx #2: (800, 55) - 2 jumps below basefee, 4 jumps below blobfee => priority -4 (blob penalty dominates)
|
||||
// Tx #3: (630, 80) - 4 jumps below basefee, 2 jumps below blobfee => priority -4 (base penalty dominates)
|
||||
//
|
||||
// Txs 1, 2, 3 share the same priority, split via tip, prefer 0 as the best
|
||||
{
|
||||
execTips: []uint64{1, 2, 3, 4},
|
||||
execFees: []uint64{800, 630, 800, 630},
|
||||
blobFees: []uint64{80, 63, 63, 80},
|
||||
blobFees: []uint64{80, 55, 55, 80},
|
||||
basefee: 1000,
|
||||
blobfee: 100,
|
||||
order: []int{1, 2, 3, 0},
|
||||
|
|
@ -142,7 +142,7 @@ func TestPriceHeapSorting(t *testing.T) {
|
|||
blobFee = uint256.NewInt(tt.blobFees[j])
|
||||
|
||||
basefeeJumps = dynamicFeeJumps(execFee)
|
||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||
blobfeeJumps = dynamicBlobFeeJumps(blobFee)
|
||||
)
|
||||
index[addr] = []*blobTxMeta{{
|
||||
id: uint64(j),
|
||||
|
|
@ -201,7 +201,7 @@ func benchmarkPriceHeapReinit(b *testing.B, datacap uint64) {
|
|||
blobFee = uint256.NewInt(rnd.Uint64())
|
||||
|
||||
basefeeJumps = dynamicFeeJumps(execFee)
|
||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||
blobfeeJumps = dynamicBlobFeeJumps(blobFee)
|
||||
)
|
||||
index[addr] = []*blobTxMeta{{
|
||||
id: uint64(i),
|
||||
|
|
@ -277,7 +277,7 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
|||
blobFee = uint256.NewInt(rnd.Uint64())
|
||||
|
||||
basefeeJumps = dynamicFeeJumps(execFee)
|
||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||
blobfeeJumps = dynamicBlobFeeJumps(blobFee)
|
||||
)
|
||||
index[addr] = []*blobTxMeta{{
|
||||
id: uint64(i),
|
||||
|
|
@ -308,7 +308,7 @@ func benchmarkPriceHeapOverflow(b *testing.B, datacap uint64) {
|
|||
blobFee = uint256.NewInt(rnd.Uint64())
|
||||
|
||||
basefeeJumps = dynamicFeeJumps(execFee)
|
||||
blobfeeJumps = dynamicFeeJumps(blobFee)
|
||||
blobfeeJumps = dynamicBlobFeeJumps(blobFee)
|
||||
)
|
||||
metas[i] = &blobTxMeta{
|
||||
id: uint64(int(blobs) + i),
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ import (
|
|||
// log1_125 is used in the eviction priority calculation.
|
||||
var log1_125 = math.Log(1.125)
|
||||
|
||||
// log1_17 is used in the eviction priority calculation for blob fees.
|
||||
// EIP-7892 (BPO) changed the ratio of target to max blobs, and with that
|
||||
// also the maximum blob fee decrease in a slot from 1.125 to approx 1.17 .
|
||||
// Since we want priorities to approximate time, we should change our log
|
||||
// calculation for blob fees.
|
||||
var log1_17 = log1_125 * 4 / 3
|
||||
|
||||
// evictionPriority calculates the eviction priority based on the algorithm
|
||||
// described in the BlobPool docs for both fee components.
|
||||
//
|
||||
|
|
@ -66,5 +73,9 @@ func dynamicFeeJumps(fee *uint256.Int) float64 {
|
|||
return math.Log(fee.Float64()) / log1_125
|
||||
}
|
||||
|
||||
func dynamicBlobFeeJumps(fee *uint256.Int) float64 {
|
||||
if fee.IsZero() {
|
||||
return 0 // can't log2 zero, should never happen outside tests, but don't choke
|
||||
}
|
||||
return math.Log(fee.Float64()) / log1_17
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,12 @@ func TestPriorityCalculation(t *testing.T) {
|
|||
txfee uint64
|
||||
result int
|
||||
}{
|
||||
{basefee: 7, txfee: 10, result: 2}, // 3.02 jumps, 4 ceil, 2 log2
|
||||
{basefee: 17_200_000_000, txfee: 17_200_000_000, result: 0}, // 0 jumps, special case 0 log2
|
||||
{basefee: 9_853_941_692, txfee: 11_085_092_510, result: 0}, // 0.99 jumps, 1 ceil, 0 log2
|
||||
{basefee: 7, txfee: 10, result: 4}, // 3.02 jumps, 4 ceil
|
||||
{basefee: 17_200_000_000, txfee: 17_200_000_000, result: 0}, // 0 jumps, special case 0
|
||||
{basefee: 9_853_941_692, txfee: 11_085_092_510, result: 1}, // 0.99 jumps, 1 ceil
|
||||
{basefee: 11_544_106_391, txfee: 10_356_781_100, result: -1}, // -0.92 jumps, -1 floor
|
||||
{basefee: 17_200_000_000, txfee: 7, result: -184}, // -183.57 jumps, -184 floor
|
||||
{basefee: 7, txfee: 17_200_000_000, result: 7}, // 183.57 jumps, 184 ceil, 7 log2
|
||||
{basefee: 7, txfee: 17_200_000_000, result: 184}, // 183.57 jumps, 184 ceil
|
||||
}
|
||||
for i, tt := range tests {
|
||||
var (
|
||||
|
|
@ -69,7 +69,7 @@ func BenchmarkPriorityCalculation(b *testing.B) {
|
|||
blobfee := uint256.NewInt(123_456_789_000) // Completely random, no idea what this will be
|
||||
|
||||
basefeeJumps := dynamicFeeJumps(basefee)
|
||||
blobfeeJumps := dynamicFeeJumps(blobfee)
|
||||
blobfeeJumps := dynamicBlobFeeJumps(blobfee)
|
||||
|
||||
// The transaction's fee cap and blob fee cap are constant across the life
|
||||
// of the transaction, so we can pre-calculate and cache them.
|
||||
|
|
@ -77,7 +77,7 @@ func BenchmarkPriorityCalculation(b *testing.B) {
|
|||
txBlobfeeJumps := make([]float64, b.N)
|
||||
for i := 0; i < b.N; i++ {
|
||||
txBasefeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rnd.Uint64()))
|
||||
txBlobfeeJumps[i] = dynamicFeeJumps(uint256.NewInt(rnd.Uint64()))
|
||||
txBlobfeeJumps[i] = dynamicBlobFeeJumps(uint256.NewInt(rnd.Uint64()))
|
||||
}
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
|
|
|
|||
Loading…
Reference in a new issue