mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
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:
parent
7b5c1696e5
commit
11ac2cc80f
2 changed files with 41 additions and 23 deletions
|
|
@ -19,8 +19,8 @@ package eip4844
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"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 {
|
if header.Number.Uint64() != parent.Number.Uint64()+1 {
|
||||||
panic("bad header pair")
|
panic("bad header pair")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the header is not malformed
|
// Verify the header is not malformed
|
||||||
if header.ExcessBlobGas == nil {
|
if header.ExcessBlobGas == nil {
|
||||||
return errors.New("header is missing excessBlobGas")
|
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 {
|
if header.BlobGasUsed == nil {
|
||||||
return errors.New("header is missing blobGasUsed")
|
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.
|
// 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 {
|
if *header.BlobGasUsed > maxBlobGas {
|
||||||
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *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.
|
// CalcBlobFee calculates the blobfee from the header's excess blob gas field.
|
||||||
func CalcBlobFee(config *params.Config2, header *types.Header) *big.Int {
|
func CalcBlobFee(config *params.Config2, header *types.Header) *big.Int {
|
||||||
schedule := params.BlobSchedule.Get(config)
|
blobcfg := scheduleAtTime(config, header.Time)
|
||||||
if schedule == nil {
|
if blobcfg == nil {
|
||||||
return new(big.Int)
|
return new(big.Int)
|
||||||
}
|
}
|
||||||
f := config.LatestFork(header.Time)
|
frac := blobcfg.UpdateFraction
|
||||||
frac := schedule[f].UpdateFraction
|
|
||||||
return fakeExponential(minBlobGasPrice, new(big.Int).SetUint64(*header.ExcessBlobGas), new(big.Int).SetUint64(frac))
|
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.
|
// MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
|
||||||
func MaxBlobsPerBlock(cfg *params.Config2, time uint64) int {
|
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.
|
// 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
|
// LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
|
||||||
// configuration, regardless of the currently active fork.
|
// configuration, regardless of the currently active fork.
|
||||||
func LatestMaxBlobsPerBlock(cfg *params.Config2) int {
|
func LatestMaxBlobsPerBlock(cfg *params.Config2) int {
|
||||||
schedule := params.BlobSchedule.Get(cfg)
|
blobcfg := scheduleAtTime(cfg, math.MaxUint64)
|
||||||
if schedule == nil {
|
return blobcfg.Max
|
||||||
return 0
|
|
||||||
}
|
|
||||||
for _, f := range slices.Backward(forks.CanonOrder) {
|
|
||||||
if f.HasBlobs() && cfg.Scheduled(f) {
|
|
||||||
return schedule[f].Max
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
|
// 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
|
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)
|
schedule := params.BlobSchedule.Get(cfg)
|
||||||
if schedule == nil {
|
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
|
// fakeExponential approximates factor * e ** (numerator / denominator) using
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,9 @@ func TestCalcBlobFee(t *testing.T) {
|
||||||
forks.London: 0,
|
forks.London: 0,
|
||||||
forks.Cancun: 0,
|
forks.Cancun: 0,
|
||||||
},
|
},
|
||||||
params.BlobSchedule{
|
params.BlobSchedule.V(map[forks.Fork]params.BlobConfig{
|
||||||
forks.Cancun: *params.DefaultCancunBlobConfig,
|
forks.Cancun: *params.DefaultCancunBlobConfig,
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
|
header := &types.Header{ExcessBlobGas: &tt.excessBlobGas}
|
||||||
have := CalcBlobFee(config, header)
|
have := CalcBlobFee(config, header)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue