@@ -23,17 +23,17 @@ import (
2323
2424 "github.com/ethereum/go-ethereum/core/types"
2525 "github.com/ethereum/go-ethereum/params"
26+ "github.com/ethereum/go-ethereum/params/forks"
2627)
2728
2829var (
29- minBlobGasPrice = big .NewInt (params .BlobTxMinBlobGasprice )
30- blobGaspriceUpdateFraction = big .NewInt (params .BlobTxBlobGaspriceUpdateFraction )
30+ minBlobGasPrice = big .NewInt (params .BlobTxMinBlobGasprice )
3131)
3232
3333// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
3434// if the current block contains no transactions, the excessBlobGas is updated
3535// accordingly.
36- func VerifyEIP4844Header (parent , header * types.Header ) error {
36+ func VerifyEIP4844Header (config * params. ChainConfig , parent , header * types.Header ) error {
3737 // Verify the header is not malformed
3838 if header .ExcessBlobGas == nil {
3939 return errors .New ("header is missing excessBlobGas" )
@@ -42,42 +42,112 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
4242 return errors .New ("header is missing blobGasUsed" )
4343 }
4444 // Verify that the blob gas used remains within reasonable limits.
45- if * header .BlobGasUsed > params .MaxBlobGasPerBlock {
46- return fmt .Errorf ("blob gas used %d exceeds maximum allowance %d" , * header .BlobGasUsed , params .MaxBlobGasPerBlock )
45+ maxBlobGas := MaxBlobGasPerBlock (config , header .Time )
46+ if * header .BlobGasUsed > maxBlobGas {
47+ return fmt .Errorf ("blob gas used %d exceeds maximum allowance %d" , * header .BlobGasUsed , maxBlobGas )
4748 }
4849 if * header .BlobGasUsed % params .BlobTxBlobGasPerBlob != 0 {
4950 return fmt .Errorf ("blob gas used %d not a multiple of blob gas per blob %d" , header .BlobGasUsed , params .BlobTxBlobGasPerBlob )
5051 }
5152 // Verify the excessBlobGas is correct based on the parent header
53+ expectedExcessBlobGas := CalcExcessBlobGas (config , parent )
54+ if * header .ExcessBlobGas != expectedExcessBlobGas {
55+ return fmt .Errorf ("invalid excessBlobGas: have %d, want %d" , * header .ExcessBlobGas , expectedExcessBlobGas )
56+ }
57+ return nil
58+ }
59+
60+ // CalcExcessBlobGas calculates the excess blob gas after applying the set of
61+ // blobs on top of the excess blob gas.
62+ func CalcExcessBlobGas (config * params.ChainConfig , parent * types.Header ) uint64 {
5263 var (
64+ targetGas = uint64 (targetBlobsPerBlock (config , parent .Time )) * params .BlobTxBlobGasPerBlob
5365 parentExcessBlobGas uint64
5466 parentBlobGasUsed uint64
5567 )
5668 if parent .ExcessBlobGas != nil {
5769 parentExcessBlobGas = * parent .ExcessBlobGas
5870 parentBlobGasUsed = * parent .BlobGasUsed
5971 }
60- expectedExcessBlobGas := CalcExcessBlobGas (parentExcessBlobGas , parentBlobGasUsed )
61- if * header .ExcessBlobGas != expectedExcessBlobGas {
62- return fmt .Errorf ("invalid excessBlobGas: have %d, want %d, parent excessBlobGas %d, parent blobDataUsed %d" ,
63- * header .ExcessBlobGas , expectedExcessBlobGas , parentExcessBlobGas , parentBlobGasUsed )
72+ excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
73+ if excessBlobGas < targetGas {
74+ return 0
6475 }
65- return nil
76+ return excessBlobGas - targetGas
6677}
6778
68- // CalcExcessBlobGas calculates the excess blob gas after applying the set of
69- // blobs on top of the excess blob gas.
70- func CalcExcessBlobGas (parentExcessBlobGas uint64 , parentBlobGasUsed uint64 ) uint64 {
71- excessBlobGas := parentExcessBlobGas + parentBlobGasUsed
72- if excessBlobGas < params .BlobTxTargetBlobGasPerBlock {
79+ // CalcBlobFee calculates the blobfee from the header's excess blob gas field.
80+ func CalcBlobFee (config * params.ChainConfig , header * types.Header ) * big.Int {
81+ var frac uint64
82+ switch config .LatestFork (header .Time ) {
83+ case forks .Prague :
84+ frac = config .BlobScheduleConfig .Prague .UpdateFraction
85+ case forks .Cancun :
86+ frac = config .BlobScheduleConfig .Cancun .UpdateFraction
87+ default :
88+ panic ("calculating blob fee on unsupported fork" )
89+ }
90+ return fakeExponential (minBlobGasPrice , new (big.Int ).SetUint64 (* header .ExcessBlobGas ), new (big.Int ).SetUint64 (frac ))
91+ }
92+
93+ // MaxBlobsPerBlock returns the max blobs per block for a block at the given timestamp.
94+ func MaxBlobsPerBlock (cfg * params.ChainConfig , time uint64 ) int {
95+ if cfg .BlobScheduleConfig == nil {
96+ return 0
97+ }
98+ var (
99+ london = cfg .LondonBlock
100+ s = cfg .BlobScheduleConfig
101+ )
102+ switch {
103+ case cfg .IsPrague (london , time ) && s .Prague != nil :
104+ return s .Prague .Max
105+ case cfg .IsCancun (london , time ) && s .Cancun != nil :
106+ return s .Cancun .Max
107+ default :
73108 return 0
74109 }
75- return excessBlobGas - params .BlobTxTargetBlobGasPerBlock
76110}
77111
78- // CalcBlobFee calculates the blobfee from the header's excess blob gas field.
79- func CalcBlobFee (excessBlobGas uint64 ) * big.Int {
80- return fakeExponential (minBlobGasPrice , new (big.Int ).SetUint64 (excessBlobGas ), blobGaspriceUpdateFraction )
112+ // MaxBlobsPerBlock returns the maximum blob gas that can be spent in a block at the given timestamp.
113+ func MaxBlobGasPerBlock (cfg * params.ChainConfig , time uint64 ) uint64 {
114+ return uint64 (MaxBlobsPerBlock (cfg , time )) * params .BlobTxBlobGasPerBlob
115+ }
116+
117+ // LatestMaxBlobsPerBlock returns the latest max blobs per block defined by the
118+ // configuration, regardless of the currently active fork.
119+ func LatestMaxBlobsPerBlock (cfg * params.ChainConfig ) int {
120+ s := cfg .BlobScheduleConfig
121+ if s == nil {
122+ return 0
123+ }
124+ switch {
125+ case s .Prague != nil :
126+ return s .Prague .Max
127+ case s .Cancun != nil :
128+ return s .Cancun .Max
129+ default :
130+ return 0
131+ }
132+ }
133+
134+ // targetBlobsPerBlock returns the target number of blobs in a block at the given timestamp.
135+ func targetBlobsPerBlock (cfg * params.ChainConfig , time uint64 ) int {
136+ if cfg .BlobScheduleConfig == nil {
137+ return 0
138+ }
139+ var (
140+ london = cfg .LondonBlock
141+ s = cfg .BlobScheduleConfig
142+ )
143+ switch {
144+ case cfg .IsPrague (london , time ) && s .Prague != nil :
145+ return s .Prague .Target
146+ case cfg .IsCancun (london , time ) && s .Cancun != nil :
147+ return s .Cancun .Target
148+ default :
149+ return 0
150+ }
81151}
82152
83153// fakeExponential approximates factor * e ** (numerator / denominator) using
0 commit comments