22
33use core:: time:: Duration ;
44use reth_chainspec:: MIN_TRANSACTION_GAS ;
5+ use reth_primitives_traits:: constants:: GAS_LIMIT_BOUND_DIVISOR ;
56use std:: { fmt:: Debug , time:: Instant } ;
67
78/// Settings for the Scroll builder.
@@ -28,9 +29,11 @@ impl ScrollBuilderConfig {
2829 Self { gas_limit, time_limit, max_da_block_size }
2930 }
3031
31- /// Returns the [`PayloadBuildingBreaker`] for the config.
32- pub ( super ) fn breaker ( & self ) -> PayloadBuildingBreaker {
33- PayloadBuildingBreaker :: new ( self . time_limit , self . gas_limit , self . max_da_block_size )
32+ /// Returns the [`PayloadBuildingBreaker`] for the config with the actual gas limit used.
33+ ///
34+ /// The `actual_gas_limit` should be the gas limit after clamping based on parent's gas limit.
35+ pub ( super ) fn breaker_with_gas_limit ( & self , actual_gas_limit : u64 ) -> PayloadBuildingBreaker {
36+ PayloadBuildingBreaker :: new ( self . time_limit , Some ( actual_gas_limit) , self . max_da_block_size )
3437 }
3538}
3639
@@ -78,6 +81,17 @@ impl PayloadBuildingBreaker {
7881 }
7982}
8083
84+ /// Calculate the gas limit for the next block based on parent and desired gas limits.
85+ ///
86+ /// The gas limit can only change by at most `parent_gas_limit / 1024` per block.
87+ /// Ref: <https://github.com/ethereum/go-ethereum/blob/88cbfab332c96edfbe99d161d9df6a40721bd786/core/block_validator.go#L166>
88+ pub fn calculate_block_gas_limit ( parent_gas_limit : u64 , desired_gas_limit : u64 ) -> u64 {
89+ let delta = ( parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR ) . saturating_sub ( 1 ) ;
90+ let min_gas_limit = parent_gas_limit. saturating_sub ( delta) ;
91+ let max_gas_limit = parent_gas_limit. saturating_add ( delta) ;
92+ desired_gas_limit. clamp ( min_gas_limit, max_gas_limit)
93+ }
94+
8195#[ cfg( test) ]
8296mod tests {
8397 use super :: * ;
@@ -128,4 +142,72 @@ mod tests {
128142 // But should still break on gas limit
129143 assert ! ( breaker. should_break( MIN_TRANSACTION_GAS + 1 , u64 :: MAX ) ) ;
130144 }
145+
146+ #[ test]
147+ fn test_calculate_block_gas_limit_within_bounds ( ) {
148+ let parent_gas_limit = GAS_LIMIT_BOUND_DIVISOR * 10 ; // 10240
149+ let delta = parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR - 1 ; // 9
150+
151+ // Desired equals parent - should return parent
152+ assert_eq ! ( calculate_block_gas_limit( parent_gas_limit, parent_gas_limit) , parent_gas_limit) ;
153+
154+ // Small increase within bounds
155+ assert_eq ! (
156+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit + 5 ) ,
157+ parent_gas_limit + 5
158+ ) ;
159+
160+ // Small decrease within bounds
161+ assert_eq ! (
162+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit - 5 ) ,
163+ parent_gas_limit - 5
164+ ) ;
165+
166+ // Exactly at max allowed increase
167+ assert_eq ! (
168+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit + delta) ,
169+ parent_gas_limit + delta
170+ ) ;
171+
172+ // Exactly at max allowed decrease
173+ assert_eq ! (
174+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit - delta) ,
175+ parent_gas_limit - delta
176+ ) ;
177+ }
178+
179+ #[ test]
180+ fn test_calculate_block_gas_limit_clamped_increase ( ) {
181+ let parent_gas_limit = GAS_LIMIT_BOUND_DIVISOR * 10 ; // 10240
182+ let delta = parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR - 1 ; // 9
183+ let max_gas_limit = parent_gas_limit + delta;
184+
185+ // Desired exceeds max - should clamp to max
186+ assert_eq ! (
187+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit + delta + 1 ) ,
188+ max_gas_limit
189+ ) ;
190+
191+ // Large increase - should clamp
192+ assert_eq ! (
193+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit * 2 ) ,
194+ max_gas_limit
195+ ) ;
196+ }
197+
198+ #[ test]
199+ fn test_calculate_block_gas_limit_clamped_decrease ( ) {
200+ let parent_gas_limit = GAS_LIMIT_BOUND_DIVISOR * 10 ; // 10240
201+ let delta = parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR - 1 ; // 9
202+ let min_gas_limit = parent_gas_limit - delta;
203+
204+ // Desired below min - should clamp to min
205+ assert_eq ! (
206+ calculate_block_gas_limit( parent_gas_limit, parent_gas_limit - delta - 1 ) ,
207+ min_gas_limit
208+ ) ;
209+
210+ // Much lower than allowed - should clamp
211+ assert_eq ! ( calculate_block_gas_limit( parent_gas_limit, 0 ) , min_gas_limit) ;
212+ }
131213}
0 commit comments