@@ -21,7 +21,7 @@ use types::{
2121 Blob , ChainSpec , EthSpec , ExecutionBlockHash , ExecutionPayload , ExecutionPayloadBellatrix ,
2222 ExecutionPayloadCapella , ExecutionPayloadDeneb , ExecutionPayloadElectra , ExecutionPayloadFulu ,
2323 ExecutionPayloadGloas , ExecutionPayloadHeader , FixedBytesExtended , ForkName , Hash256 ,
24- KzgProofs , Transaction , Transactions , Uint256 ,
24+ KzgProofs , Slot , Transaction , Transactions , Uint256 ,
2525} ;
2626
2727use super :: DEFAULT_TERMINAL_BLOCK ;
@@ -265,6 +265,37 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
265265 ForkName :: Bellatrix
266266 }
267267
268+ /// Get the timestamp at which `fork` activates.
269+ ///
270+ /// This function will panic if the `fork` is not enabled or is `<= ForkName::Bellatrix`.
271+ pub fn get_fork_timestamp_post_capella ( & self , fork : ForkName ) -> u64 {
272+ match fork {
273+ ForkName :: Gloas => self . amsterdam_time ,
274+ ForkName :: Fulu => self . osaka_time ,
275+ ForkName :: Electra => self . prague_time ,
276+ ForkName :: Deneb => self . cancun_time ,
277+ ForkName :: Capella => self . shanghai_time ,
278+ _ => panic ! ( "only the Capella fork or later is supported" ) ,
279+ }
280+ . unwrap_or_else ( || panic ! ( "fork is {fork} but no corresponding timestamp is set" ) )
281+ }
282+
283+ /// This is a slightly nasty method for converting timestamps to slots, but it will suffice
284+ /// until we can plumb through a slot clock.
285+ pub fn timestamp_to_slot_post_capella ( & self , timestamp : u64 ) -> Slot {
286+ let fork = self . get_fork_at_timestamp ( timestamp) ;
287+ let fork_epoch = self . spec . fork_epoch ( fork) . unwrap ( ) ;
288+ let fork_timestamp = self . get_fork_timestamp_post_capella ( fork) ;
289+
290+ // Number of slots since fork.
291+ let slot_offset = timestamp
292+ . checked_sub ( fork_timestamp)
293+ . expect ( "timestamp should be >= fork timestamp" )
294+ / self . spec . seconds_per_slot ;
295+
296+ fork_epoch. start_slot ( E :: slots_per_epoch ( ) ) + Slot :: new ( slot_offset)
297+ }
298+
268299 pub fn execution_block_by_number ( & self , number : u64 ) -> Option < ExecutionBlock > {
269300 self . block_by_number ( number)
270301 . map ( |block| block. as_execution_block ( self . terminal_total_difficulty ) )
@@ -734,9 +765,10 @@ impl<E: EthSpec> ExecutionBlockGenerator<E> {
734765 if fork_name. deneb_enabled ( ) {
735766 // get random number between 0 and Max Blobs
736767 let mut rng = self . rng . lock ( ) ;
737- // TODO(EIP-7892): see FIXME below
738- // FIXME: this will break with BPO forks. This function needs to calculate the epoch based on block timestamp..
739- let max_blobs = self . spec . max_blobs_per_block_within_fork ( fork_name) as usize ;
768+ let epoch = self
769+ . timestamp_to_slot_post_capella ( execution_payload. timestamp ( ) )
770+ . epoch ( E :: slots_per_epoch ( ) ) ;
771+ let max_blobs = self . spec . max_blobs_per_block ( epoch) as usize ;
740772 let num_blobs = rng. random_range ( self . min_blobs_count ..=max_blobs) ;
741773 let ( bundle, transactions) = generate_blobs ( num_blobs, fork_name) ?;
742774 for tx in Vec :: from ( transactions) {
0 commit comments