@@ -246,6 +246,7 @@ pub struct ChainSpec {
246246 * Networking Fulu
247247 */
248248 blob_schedule : BlobSchedule ,
249+ min_epochs_for_data_column_sidecars_requests : u64 ,
249250
250251 /*
251252 * Networking Derived
@@ -733,6 +734,20 @@ impl ChainSpec {
733734 Ok ( std:: cmp:: max ( custody_column_count, self . samples_per_slot ) )
734735 }
735736
737+ /// Returns the min epoch for blob / data column sidecar requests based on the current epoch.
738+ /// Switch to use the column sidecar config once the `blob_retention_epoch` has passed Fulu fork epoch.
739+ pub fn min_epoch_data_availability_boundary ( & self , current_epoch : Epoch ) -> Option < Epoch > {
740+ let fork_epoch = self . deneb_fork_epoch ?;
741+ let blob_retention_epoch =
742+ current_epoch. saturating_sub ( self . min_epochs_for_blob_sidecars_requests ) ;
743+ match self . fulu_fork_epoch {
744+ Some ( fulu_fork_epoch) if blob_retention_epoch > fulu_fork_epoch => Some (
745+ current_epoch. saturating_sub ( self . min_epochs_for_data_column_sidecars_requests ) ,
746+ ) ,
747+ _ => Some ( std:: cmp:: max ( fork_epoch, blob_retention_epoch) ) ,
748+ }
749+ }
750+
736751 pub fn all_data_column_sidecar_subnets ( & self ) -> impl Iterator < Item = DataColumnSubnetId > {
737752 ( 0 ..self . data_column_sidecar_subnet_count ) . map ( DataColumnSubnetId :: new)
738753 }
@@ -1020,6 +1035,8 @@ impl ChainSpec {
10201035 * Networking Fulu specific
10211036 */
10221037 blob_schedule : BlobSchedule :: default ( ) ,
1038+ min_epochs_for_data_column_sidecars_requests :
1039+ default_min_epochs_for_data_column_sidecars_requests ( ) ,
10231040
10241041 /*
10251042 * Application specific
@@ -1356,6 +1373,8 @@ impl ChainSpec {
13561373 * Networking Fulu specific
13571374 */
13581375 blob_schedule : BlobSchedule :: default ( ) ,
1376+ min_epochs_for_data_column_sidecars_requests :
1377+ default_min_epochs_for_data_column_sidecars_requests ( ) ,
13591378
13601379 /*
13611380 * Application specific
@@ -1654,6 +1673,9 @@ pub struct Config {
16541673 #[ serde( default = "default_balance_per_additional_custody_group" ) ]
16551674 #[ serde( with = "serde_utils::quoted_u64" ) ]
16561675 balance_per_additional_custody_group : u64 ,
1676+ #[ serde( default = "default_min_epochs_for_data_column_sidecars_requests" ) ]
1677+ #[ serde( with = "serde_utils::quoted_u64" ) ]
1678+ min_epochs_for_data_column_sidecars_requests : u64 ,
16571679}
16581680
16591681fn default_bellatrix_fork_version ( ) -> [ u8 ; 4 ] {
@@ -1827,6 +1849,10 @@ const fn default_balance_per_additional_custody_group() -> u64 {
18271849 32000000000
18281850}
18291851
1852+ const fn default_min_epochs_for_data_column_sidecars_requests ( ) -> u64 {
1853+ 4096
1854+ }
1855+
18301856fn max_blocks_by_root_request_common ( max_request_blocks : u64 ) -> usize {
18311857 let max_request_blocks = max_request_blocks as usize ;
18321858 RuntimeVariableList :: < Hash256 > :: from_vec (
@@ -2038,6 +2064,8 @@ impl Config {
20382064 blob_schedule : spec. blob_schedule . clone ( ) ,
20392065 validator_custody_requirement : spec. validator_custody_requirement ,
20402066 balance_per_additional_custody_group : spec. balance_per_additional_custody_group ,
2067+ min_epochs_for_data_column_sidecars_requests : spec
2068+ . min_epochs_for_data_column_sidecars_requests ,
20412069 }
20422070 }
20432071
@@ -2119,6 +2147,7 @@ impl Config {
21192147 ref blob_schedule,
21202148 validator_custody_requirement,
21212149 balance_per_additional_custody_group,
2150+ min_epochs_for_data_column_sidecars_requests,
21222151 } = self ;
21232152
21242153 if preset_base != E :: spec_name ( ) . to_string ( ) . as_str ( ) {
@@ -2205,6 +2234,7 @@ impl Config {
22052234 blob_schedule : blob_schedule. clone ( ) ,
22062235 validator_custody_requirement,
22072236 balance_per_additional_custody_group,
2237+ min_epochs_for_data_column_sidecars_requests,
22082238
22092239 ..chain_spec. clone ( )
22102240 } )
@@ -2343,6 +2373,7 @@ mod tests {
23432373mod yaml_tests {
23442374 use super :: * ;
23452375 use paste:: paste;
2376+ use std:: sync:: Arc ;
23462377 use tempfile:: NamedTempFile ;
23472378
23482379 #[ test]
@@ -2642,4 +2673,65 @@ mod yaml_tests {
26422673 let _ = spec. max_message_size ( ) ;
26432674 let _ = spec. max_compressed_len ( ) ;
26442675 }
2676+
2677+ #[ test]
2678+ fn min_epochs_for_data_sidecar_requests_deneb ( ) {
2679+ type E = MainnetEthSpec ;
2680+ let spec = Arc :: new ( ForkName :: Deneb . make_genesis_spec ( E :: default_spec ( ) ) ) ;
2681+ let blob_retention_epochs = spec. min_epochs_for_blob_sidecars_requests ;
2682+
2683+ // `min_epochs_for_data_sidecar_requests` cannot be earlier than Deneb fork epoch.
2684+ assert_eq ! (
2685+ spec. deneb_fork_epoch,
2686+ spec. min_epoch_data_availability_boundary( Epoch :: new( blob_retention_epochs / 2 ) )
2687+ ) ;
2688+
2689+ let current_epoch = Epoch :: new ( blob_retention_epochs * 2 ) ;
2690+ let expected_min_blob_epoch = current_epoch - blob_retention_epochs;
2691+ assert_eq ! (
2692+ Some ( expected_min_blob_epoch) ,
2693+ spec. min_epoch_data_availability_boundary( current_epoch)
2694+ ) ;
2695+ }
2696+
2697+ #[ test]
2698+ fn min_epochs_for_data_sidecar_requests_fulu ( ) {
2699+ type E = MainnetEthSpec ;
2700+ let spec = {
2701+ let mut spec = ForkName :: Deneb . make_genesis_spec ( E :: default_spec ( ) ) ;
2702+ // 4096 * 2 = 8192
2703+ spec. fulu_fork_epoch = Some ( Epoch :: new ( spec. min_epochs_for_blob_sidecars_requests * 2 ) ) ;
2704+ // set a different value for testing purpose, 4096 / 2 = 2048
2705+ spec. min_epochs_for_data_column_sidecars_requests =
2706+ spec. min_epochs_for_blob_sidecars_requests / 2 ;
2707+ Arc :: new ( spec)
2708+ } ;
2709+ let blob_retention_epochs = spec. min_epochs_for_blob_sidecars_requests ;
2710+ let data_column_retention_epochs = spec. min_epochs_for_data_column_sidecars_requests ;
2711+
2712+ // `min_epochs_for_data_sidecar_requests` at fulu fork epoch still uses `min_epochs_for_blob_sidecars_requests`
2713+ let fulu_fork_epoch = spec. fulu_fork_epoch . unwrap ( ) ;
2714+ let expected_blob_retention_epoch = fulu_fork_epoch - blob_retention_epochs;
2715+ assert_eq ! (
2716+ Some ( expected_blob_retention_epoch) ,
2717+ spec. min_epoch_data_availability_boundary( fulu_fork_epoch)
2718+ ) ;
2719+
2720+ // `min_epochs_for_data_sidecar_requests` at fulu fork epoch + min_epochs_for_blob_sidecars_request
2721+ let blob_retention_epoch_after_fulu = fulu_fork_epoch + blob_retention_epochs;
2722+ let expected_blob_retention_epoch = blob_retention_epoch_after_fulu - blob_retention_epochs;
2723+ assert_eq ! (
2724+ Some ( expected_blob_retention_epoch) ,
2725+ spec. min_epoch_data_availability_boundary( blob_retention_epoch_after_fulu)
2726+ ) ;
2727+
2728+ // After the final blob retention epoch, `min_epochs_for_data_sidecar_requests` should be calculated
2729+ // using `min_epochs_for_data_column_sidecars_request`
2730+ let current_epoch = blob_retention_epoch_after_fulu + 1 ;
2731+ let expected_data_column_retention_epoch = current_epoch - data_column_retention_epochs;
2732+ assert_eq ! (
2733+ Some ( expected_data_column_retention_epoch) ,
2734+ spec. min_epoch_data_availability_boundary( current_epoch)
2735+ ) ;
2736+ }
26452737}
0 commit comments