consensus/misc/eip4844: make it work

It's not great to call scheduleAtTime so many times. The function is much more
expensive now since it has to establish the fork order every time.
A later refactoring needs to turn it around to compute the order only once.
This commit is contained in:
Felix Lange 2025-07-24 23:27:00 +02:00
parent 7b5c1696e5
commit 11ac2cc80f
2 changed files with 41 additions and 23 deletions

View file

@ -19,8 +19,8 @@ package eip4844
import (
"errors"
"fmt"
"math"
"math/big"
"slices"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
@ -38,6 +38,7 @@ func VerifyEIP4844Header(config *params.Config2, parent, header *types.Header) e
if header.Number.Uint64() != parent.Number.Uint64()+1 {
panic("bad header pair")
}
// Verify the header is not malformed
if header.ExcessBlobGas == nil {
return errors.New("header is missing excessBlobGas")
@ -45,8 +46,14 @@ func VerifyEIP4844Header(config *params.Config2, parent, header *types.Header) e
if header.BlobGasUsed == nil {
return errors.New("header is missing blobGasUsed")
}
blobcfg := scheduleAtTime(config, header.Time)
if blobcfg == nil {
return fmt.Errorf("blob schedule is undefined at time %d", header.Time)
}
// Verify that the blob gas used remains within reasonable limits.
maxBlobGas := MaxBlobGasPerBlock(config, header.Time)
maxBlobGas := uint64(blobcfg.Max) * params.BlobTxBlobGasPerBlob
if *header.BlobGasUsed > maxBlobGas {
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, maxBlobGas)
}
@ -101,18 +108,21 @@ func CalcExcessBlobGas(config *params.Config2, parent *types.Header, headTimesta
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
func CalcBlobFee(config *params.Config2, header *types.Header) *big.Int {
schedule := params.BlobSchedule.Get(config)
if schedule == nil {
blobcfg := scheduleAtTime(config, header.Time)
if blobcfg == nil {
return new(big.Int)
}
f := config.LatestFork(header.Time)
frac := schedule[f].UpdateFraction
frac := blobcfg.UpdateFraction
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(frac))
}
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
func MaxBlobsPerBlock(cfg *params.Config2, time uint64) int {
return scheduleAtTime(cfg, time).Max
blobcfg := scheduleAtTime(cfg, time)
if blobcfg == nil {
return 0
}
return blobcfg.Max
}
// MaxBlobsPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp.
@ -123,16 +133,8 @@ func MaxBlobGasPerBlock(cfg *params.Config2, time uint64) uint64 {
// LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
// configuration, regardless of the currently active fork.
func LatestMaxBlobsPerBlock(cfg *params.Config2) int {
schedule := params.BlobSchedule.Get(cfg)
if schedule == nil {
return 0
}
for _, f := range slices.Backward(forks.CanonOrder) {
if f.HasBlobs() && cfg.Scheduled(f) {
return schedule[f].Max
}
}
return 0
blobcfg := scheduleAtTime(cfg, math.MaxUint64)
return blobcfg.Max
}
// targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
@ -140,13 +142,29 @@ func targetBlobsPerBlock(cfg *params.Config2, time uint64) int {
return scheduleAtTime(cfg, time).Target
}
func scheduleAtTime(cfg *params.Config2, time uint64) params.BlobConfig {
// scheduleAtTime resolves the blob schedule at the given timestamp.
func scheduleAtTime(cfg *params.Config2, time uint64) *params.BlobConfig {
schedule := params.BlobSchedule.Get(cfg)
if schedule == nil {
return params.BlobConfig{}
return nil
}
f := cfg.LatestFork(time)
return schedule[f]
// Find the latest fork defined by the schedule.
forkList := make([]forks.Fork, 0, len(schedule))
for f := range schedule {
act, ok := cfg.Activation(f)
if ok && act <= time {
forkList = append(forkList, f)
}
}
forkList = forks.DependencyOrder(forkList)
// Return the blob config of the last available fork.
if len(forkList) == 0 {
return nil
}
blobcfg := schedule[forkList[len(forkList)-1]]
return &blobcfg
}
// fakeExponential approximates factor * e ** (numerator / denominator) using

View file

@ -88,9 +88,9 @@ func TestCalcBlobFee(t *testing.T) {
forks.London: 0,
forks.Cancun: 0,
},
params.BlobSchedule{
params.BlobSchedule.V(map[forks.Fork]params.BlobConfig{
forks.Cancun: *params.DefaultCancunBlobConfig,
},
}),
)
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
have := CalcBlobFee(config, header)