@@ -23,17 +23,17 @@ import (
23
23
24
24
"github.com/ethereum/go-ethereum/core/types"
25
25
"github.com/ethereum/go-ethereum/params"
26
+ "github.com/ethereum/go-ethereum/params/forks"
26
27
)
27
28
28
29
var (
29
- minBlobGasPrice = big .NewInt (params .BlobTxMinBlobGasprice )
30
- blobGaspriceUpdateFraction = big .NewInt (params .BlobTxBlobGaspriceUpdateFraction )
30
+ minBlobGasPrice = big .NewInt (params .BlobTxMinBlobGasprice )
31
31
)
32
32
33
33
// VerifyEIP4844Header verifies the presence of the excessBlobGas field and that
34
34
// if the current block contains no transactions, the excessBlobGas is updated
35
35
// accordingly.
36
- func VerifyEIP4844Header (parent , header * types.Header ) error {
36
+ func VerifyEIP4844Header (config * params. ChainConfig , parent , header * types.Header ) error {
37
37
// Verify the header is not malformed
38
38
if header .ExcessBlobGas == nil {
39
39
return errors .New ("header is missing excessBlobGas" )
@@ -42,42 +42,112 @@ func VerifyEIP4844Header(parent, header *types.Header) error {
42
42
return errors .New ("header is missing blobGasUsed" )
43
43
}
44
44
// 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 )
47
48
}
48
49
if * header .BlobGasUsed % params .BlobTxBlobGasPerBlob != 0 {
49
50
return fmt .Errorf ("blob gas used %d not a multiple of blob gas per blob %d" , header .BlobGasUsed , params .BlobTxBlobGasPerBlob )
50
51
}
51
52
// 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 {
52
63
var (
64
+ targetGas = uint64 (targetBlobsPerBlock (config , parent .Time )) * params .BlobTxBlobGasPerBlob
53
65
parentExcessBlobGas uint64
54
66
parentBlobGasUsed uint64
55
67
)
56
68
if parent .ExcessBlobGas != nil {
57
69
parentExcessBlobGas = * parent .ExcessBlobGas
58
70
parentBlobGasUsed = * parent .BlobGasUsed
59
71
}
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
64
75
}
65
- return nil
76
+ return excessBlobGas - targetGas
66
77
}
67
78
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 :
73
108
return 0
74
109
}
75
- return excessBlobGas - params .BlobTxTargetBlobGasPerBlock
76
110
}
77
111
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
+ }
81
151
}
82
152
83
153
// fakeExponential approximates factor * e ** (numerator / denominator) using
0 commit comments