github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/txpool/blobpool/priority.go (about) 1 // Copyright 2023 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package blobpool 18 19 import ( 20 "math" 21 "math/bits" 22 23 "github.com/holiman/uint256" 24 ) 25 26 // log1_125 is used in the eviction priority calculation. 27 var log1_125 = math.Log(1.125) 28 29 // evictionPriority calculates the eviction priority based on the algorithm 30 // described in the BlobPool docs for both fee components. 31 // 32 // This method takes about 8ns on a very recent laptop CPU, recalculating about 33 // 125 million transaction priority values per second. 34 func evictionPriority(basefeeJumps float64, txBasefeeJumps, blobfeeJumps, txBlobfeeJumps float64) int { 35 var ( 36 basefeePriority = evictionPriority1D(basefeeJumps, txBasefeeJumps) 37 blobfeePriority = evictionPriority1D(blobfeeJumps, txBlobfeeJumps) 38 ) 39 if basefeePriority < blobfeePriority { 40 return basefeePriority 41 } 42 return blobfeePriority 43 } 44 45 // evictionPriority1D calculates the eviction priority based on the algorithm 46 // described in the BlobPool docs for a single fee component. 47 func evictionPriority1D(basefeeJumps float64, txfeeJumps float64) int { 48 jumps := txfeeJumps - basefeeJumps 49 if int(jumps) == 0 { 50 return 0 // can't log2 0 51 } 52 if jumps < 0 { 53 return -intLog2(uint(-math.Floor(jumps))) 54 } 55 return intLog2(uint(math.Ceil(jumps))) 56 } 57 58 // dynamicFeeJumps calculates the log1.125(fee), namely the number of fee jumps 59 // needed to reach the requested one. We only use it when calculating the jumps 60 // between 2 fees, so it doesn't matter from what exact number it returns. 61 // It returns the result from (0, 1, 1.125). 62 // 63 // This method is very expensive, taking about 75ns on a very recent laptop CPU, 64 // but the result does not change with the lifetime of a transaction, so it can 65 // be cached. 66 func dynamicFeeJumps(fee *uint256.Int) float64 { 67 if fee.IsZero() { 68 return 0 // can't log2 zero, should never happen outside tests, but don't choke 69 } 70 return math.Log(fee.Float64()) / log1_125 71 } 72 73 // intLog2 is a helper to calculate the integral part of a log2 of an unsigned 74 // integer. It is a very specific calculation that's not particularly useful in 75 // general, but it's what we need here (it's fast). 76 func intLog2(n uint) int { 77 switch { 78 case n == 0: 79 panic("log2(0) is undefined") 80 81 case n < 2048: 82 return bits.UintSize - bits.LeadingZeros(n) - 1 83 84 default: 85 // The input is log1.125(uint256) = log2(uint256) / log2(1.125). At the 86 // most extreme, log2(uint256) will be a bit below 257, and the constant 87 // log2(1.125) ~= 0.17. The larges input thus is ~257 / ~0.17 ~= ~1511. 88 panic("dynamic fee jump diffs cannot reach this") 89 } 90 }