|
| 1 | +package types |
| 2 | + |
| 3 | +import ( |
| 4 | + "math/big" |
| 5 | + |
| 6 | + "github.com/morph-l2/go-ethereum/log" |
| 7 | +) |
| 8 | + |
| 9 | +// BlobFeeConfig is used to configure blob fee calculation parameters. |
| 10 | +type BlobFeeConfig struct { |
| 11 | + ChainID *big.Int |
| 12 | + |
| 13 | + // LondonBlock is the London block number (used for time determination). |
| 14 | + LondonBlock *big.Int |
| 15 | + |
| 16 | + // Timestamps for each EIP upgrade (Unix timestamp, seconds). |
| 17 | + CancunTime *uint64 // EIP-4844 (Cancun) |
| 18 | + PragueTime *uint64 // Prague |
| 19 | + OsakaTime *uint64 // Osaka |
| 20 | + BPO1Time *uint64 // BPO1 |
| 21 | + BPO2Time *uint64 // BPO2 |
| 22 | + BPO3Time *uint64 // BPO3 |
| 23 | + BPO4Time *uint64 // BPO4 |
| 24 | + BPO5Time *uint64 // BPO5 |
| 25 | + |
| 26 | + // BlobConfig corresponding to each EIP. |
| 27 | + Cancun *BlobConfig |
| 28 | + Prague *BlobConfig |
| 29 | + Osaka *BlobConfig |
| 30 | + BPO1 *BlobConfig |
| 31 | + BPO2 *BlobConfig |
| 32 | + BPO3 *BlobConfig |
| 33 | + BPO4 *BlobConfig |
| 34 | + BPO5 *BlobConfig |
| 35 | + |
| 36 | + Default *BlobConfig |
| 37 | +} |
| 38 | + |
| 39 | +// BlobConfig contains the parameters required for blob fee calculation. |
| 40 | +type BlobConfig struct { |
| 41 | + // UpdateFraction is the denominator in the fakeExponential function. |
| 42 | + UpdateFraction uint64 |
| 43 | +} |
| 44 | + |
| 45 | +// Time determination methods (referencing go-ethereum logic). |
| 46 | +// IsCancun returns whether time is either equal to the Cancun fork time or greater. |
| 47 | +func (c *BlobFeeConfig) IsCancun(num *big.Int, time uint64) bool { |
| 48 | + return c.IsLondon(num) && isTimestampForked(c.CancunTime, time) |
| 49 | +} |
| 50 | + |
| 51 | +// IsPrague returns whether time is either equal to the Prague fork time or greater. |
| 52 | +func (c *BlobFeeConfig) IsPrague(num *big.Int, time uint64) bool { |
| 53 | + return c.IsLondon(num) && isTimestampForked(c.PragueTime, time) |
| 54 | +} |
| 55 | + |
| 56 | +// IsOsaka returns whether time is either equal to the Osaka fork time or greater. |
| 57 | +func (c *BlobFeeConfig) IsOsaka(num *big.Int, time uint64) bool { |
| 58 | + return c.IsLondon(num) && isTimestampForked(c.OsakaTime, time) |
| 59 | +} |
| 60 | + |
| 61 | +// IsBPO1 returns whether time is either equal to the BPO1 fork time or greater. |
| 62 | +func (c *BlobFeeConfig) IsBPO1(num *big.Int, time uint64) bool { |
| 63 | + return c.IsLondon(num) && isTimestampForked(c.BPO1Time, time) |
| 64 | +} |
| 65 | + |
| 66 | +// IsBPO2 returns whether time is either equal to the BPO2 fork time or greater. |
| 67 | +func (c *BlobFeeConfig) IsBPO2(num *big.Int, time uint64) bool { |
| 68 | + return c.IsLondon(num) && isTimestampForked(c.BPO2Time, time) |
| 69 | +} |
| 70 | + |
| 71 | +// IsBPO3 returns whether time is either equal to the BPO3 fork time or greater. |
| 72 | +func (c *BlobFeeConfig) IsBPO3(num *big.Int, time uint64) bool { |
| 73 | + return c.IsLondon(num) && isTimestampForked(c.BPO3Time, time) |
| 74 | +} |
| 75 | + |
| 76 | +// IsBPO4 returns whether time is either equal to the BPO4 fork time or greater. |
| 77 | +func (c *BlobFeeConfig) IsBPO4(num *big.Int, time uint64) bool { |
| 78 | + return c.IsLondon(num) && isTimestampForked(c.BPO4Time, time) |
| 79 | +} |
| 80 | + |
| 81 | +// IsBPO5 returns whether time is either equal to the BPO5 fork time or greater. |
| 82 | +func (c *BlobFeeConfig) IsBPO5(num *big.Int, time uint64) bool { |
| 83 | + return c.IsLondon(num) && isTimestampForked(c.BPO5Time, time) |
| 84 | +} |
| 85 | + |
| 86 | +// IsLondon returns whether num is either equal to the London fork block or greater. |
| 87 | +func (c *BlobFeeConfig) IsLondon(num *big.Int) bool { |
| 88 | + return isBlockForked(c.LondonBlock, num) |
| 89 | +} |
| 90 | + |
| 91 | +// GetBlobFeeDenominator returns the corresponding UpdateFraction based on the time. |
| 92 | +func GetBlobFeeDenominator(blobFeeConfig *BlobFeeConfig, blockTime uint64) *big.Int { |
| 93 | + if blobFeeConfig == nil { |
| 94 | + // If not configured, use default value. |
| 95 | + log.Warn("BlobFeeConfig not set, using default denominator", |
| 96 | + "default", DefaultOsakaBlobConfig) |
| 97 | + return new(big.Int).SetUint64(DefaultOsakaBlobConfig.UpdateFraction) |
| 98 | + } |
| 99 | + |
| 100 | + cfg := blobFeeConfig |
| 101 | + londonBlock := cfg.LondonBlock // London block number for fork determination. |
| 102 | + |
| 103 | + // Check in priority order from high to low (BPO5 -> BPO4 -> ... -> Cancun). |
| 104 | + var blobConfig *BlobConfig |
| 105 | + |
| 106 | + // Check BPO5 |
| 107 | + if cfg.BPO5Time != nil && cfg.IsBPO5(londonBlock, blockTime) && cfg.BPO5 != nil { |
| 108 | + blobConfig = cfg.BPO5 |
| 109 | + } else if cfg.BPO4Time != nil && cfg.IsBPO4(londonBlock, blockTime) && cfg.BPO4 != nil { |
| 110 | + blobConfig = cfg.BPO4 |
| 111 | + } else if cfg.BPO3Time != nil && cfg.IsBPO3(londonBlock, blockTime) && cfg.BPO3 != nil { |
| 112 | + blobConfig = cfg.BPO3 |
| 113 | + } else if cfg.BPO2Time != nil && cfg.IsBPO2(londonBlock, blockTime) && cfg.BPO2 != nil { |
| 114 | + blobConfig = cfg.BPO2 |
| 115 | + } else if cfg.BPO1Time != nil && cfg.IsBPO1(londonBlock, blockTime) && cfg.BPO1 != nil { |
| 116 | + blobConfig = cfg.BPO1 |
| 117 | + } else if cfg.OsakaTime != nil && cfg.IsOsaka(londonBlock, blockTime) && cfg.Osaka != nil { |
| 118 | + blobConfig = cfg.Osaka |
| 119 | + } else if cfg.PragueTime != nil && cfg.IsPrague(londonBlock, blockTime) && cfg.Prague != nil { |
| 120 | + blobConfig = cfg.Prague |
| 121 | + } else if cfg.CancunTime != nil && cfg.IsCancun(londonBlock, blockTime) && cfg.Cancun != nil { |
| 122 | + blobConfig = cfg.Cancun |
| 123 | + } else if cfg.Default != nil { |
| 124 | + blobConfig = cfg.Default |
| 125 | + } |
| 126 | + |
| 127 | + if blobConfig == nil { |
| 128 | + log.Warn("No blob config found for current time, using default", |
| 129 | + "blockTime", blockTime, |
| 130 | + "londonBlock", londonBlock, |
| 131 | + "default", DefaultOsakaBlobConfig) |
| 132 | + return new(big.Int).SetUint64(DefaultOsakaBlobConfig.UpdateFraction) |
| 133 | + } |
| 134 | + |
| 135 | + return new(big.Int).SetUint64(blobConfig.UpdateFraction) |
| 136 | +} |
| 137 | + |
| 138 | +// isBlockForked returns whether a fork scheduled at block s is active at the |
| 139 | +// given head block. Whilst this method is the same as isTimestampForked, they |
| 140 | +// are explicitly separate for clearer reading. |
| 141 | +func isBlockForked(s, head *big.Int) bool { |
| 142 | + if s == nil || head == nil { |
| 143 | + return false |
| 144 | + } |
| 145 | + return s.Cmp(head) <= 0 |
| 146 | +} |
| 147 | + |
| 148 | +// isTimestampForked returns whether a fork scheduled at timestamp s is active |
| 149 | +// at the given head timestamp. Whilst this method is the same as isBlockForked, |
| 150 | +// they are explicitly separate for clearer reading. |
| 151 | +func isTimestampForked(s *uint64, head uint64) bool { |
| 152 | + if s == nil { |
| 153 | + return false |
| 154 | + } |
| 155 | + return *s <= head |
| 156 | +} |
0 commit comments