@@ -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
@@ -740,6 +741,20 @@ impl ChainSpec {
740741 Ok ( std:: cmp:: max ( custody_group_count, self . samples_per_slot ) )
741742 }
742743
744+ /// Returns the min epoch for blob / data column sidecar requests based on the current epoch.
745+ /// Switch to use the column sidecar config once the `blob_retention_epoch` has passed Fulu fork epoch.
746+ pub fn min_epoch_data_availability_boundary ( & self , current_epoch : Epoch ) -> Option < Epoch > {
747+ let fork_epoch = self . deneb_fork_epoch ?;
748+ let blob_retention_epoch =
749+ current_epoch. saturating_sub ( self . min_epochs_for_blob_sidecars_requests ) ;
750+ match self . fulu_fork_epoch {
751+ Some ( fulu_fork_epoch) if blob_retention_epoch > fulu_fork_epoch => Some (
752+ current_epoch. saturating_sub ( self . min_epochs_for_data_column_sidecars_requests ) ,
753+ ) ,
754+ _ => Some ( std:: cmp:: max ( fork_epoch, blob_retention_epoch) ) ,
755+ }
756+ }
757+
743758 pub fn all_data_column_sidecar_subnets ( & self ) -> impl Iterator < Item = DataColumnSubnetId > {
744759 ( 0 ..self . data_column_sidecar_subnet_count ) . map ( DataColumnSubnetId :: new)
745760 }
@@ -1027,6 +1042,8 @@ impl ChainSpec {
10271042 * Networking Fulu specific
10281043 */
10291044 blob_schedule : BlobSchedule :: default ( ) ,
1045+ min_epochs_for_data_column_sidecars_requests :
1046+ default_min_epochs_for_data_column_sidecars_requests ( ) ,
10301047
10311048 /*
10321049 * Application specific
@@ -1363,6 +1380,8 @@ impl ChainSpec {
13631380 * Networking Fulu specific
13641381 */
13651382 blob_schedule : BlobSchedule :: default ( ) ,
1383+ min_epochs_for_data_column_sidecars_requests :
1384+ default_min_epochs_for_data_column_sidecars_requests ( ) ,
13661385
13671386 /*
13681387 * Application specific
@@ -1661,6 +1680,9 @@ pub struct Config {
16611680 #[ serde( default = "default_balance_per_additional_custody_group" ) ]
16621681 #[ serde( with = "serde_utils::quoted_u64" ) ]
16631682 balance_per_additional_custody_group : u64 ,
1683+ #[ serde( default = "default_min_epochs_for_data_column_sidecars_requests" ) ]
1684+ #[ serde( with = "serde_utils::quoted_u64" ) ]
1685+ min_epochs_for_data_column_sidecars_requests : u64 ,
16641686}
16651687
16661688fn default_bellatrix_fork_version ( ) -> [ u8 ; 4 ] {
@@ -1834,6 +1856,10 @@ const fn default_balance_per_additional_custody_group() -> u64 {
18341856 32000000000
18351857}
18361858
1859+ const fn default_min_epochs_for_data_column_sidecars_requests ( ) -> u64 {
1860+ 4096
1861+ }
1862+
18371863fn max_blocks_by_root_request_common ( max_request_blocks : u64 ) -> usize {
18381864 let max_request_blocks = max_request_blocks as usize ;
18391865 RuntimeVariableList :: < Hash256 > :: from_vec (
@@ -2045,6 +2071,8 @@ impl Config {
20452071 blob_schedule : spec. blob_schedule . clone ( ) ,
20462072 validator_custody_requirement : spec. validator_custody_requirement ,
20472073 balance_per_additional_custody_group : spec. balance_per_additional_custody_group ,
2074+ min_epochs_for_data_column_sidecars_requests : spec
2075+ . min_epochs_for_data_column_sidecars_requests ,
20482076 }
20492077 }
20502078
@@ -2126,6 +2154,7 @@ impl Config {
21262154 ref blob_schedule,
21272155 validator_custody_requirement,
21282156 balance_per_additional_custody_group,
2157+ min_epochs_for_data_column_sidecars_requests,
21292158 } = self ;
21302159
21312160 if preset_base != E :: spec_name ( ) . to_string ( ) . as_str ( ) {
@@ -2212,6 +2241,7 @@ impl Config {
22122241 blob_schedule : blob_schedule. clone ( ) ,
22132242 validator_custody_requirement,
22142243 balance_per_additional_custody_group,
2244+ min_epochs_for_data_column_sidecars_requests,
22152245
22162246 ..chain_spec. clone ( )
22172247 } )
@@ -2350,6 +2380,7 @@ mod tests {
23502380mod yaml_tests {
23512381 use super :: * ;
23522382 use paste:: paste;
2383+ use std:: sync:: Arc ;
23532384 use tempfile:: NamedTempFile ;
23542385
23552386 #[ test]
@@ -2649,4 +2680,65 @@ mod yaml_tests {
26492680 let _ = spec. max_message_size ( ) ;
26502681 let _ = spec. max_compressed_len ( ) ;
26512682 }
2683+
2684+ #[ test]
2685+ fn min_epochs_for_data_sidecar_requests_deneb ( ) {
2686+ type E = MainnetEthSpec ;
2687+ let spec = Arc :: new ( ForkName :: Deneb . make_genesis_spec ( E :: default_spec ( ) ) ) ;
2688+ let blob_retention_epochs = spec. min_epochs_for_blob_sidecars_requests ;
2689+
2690+ // `min_epochs_for_data_sidecar_requests` cannot be earlier than Deneb fork epoch.
2691+ assert_eq ! (
2692+ spec. deneb_fork_epoch,
2693+ spec. min_epoch_data_availability_boundary( Epoch :: new( blob_retention_epochs / 2 ) )
2694+ ) ;
2695+
2696+ let current_epoch = Epoch :: new ( blob_retention_epochs * 2 ) ;
2697+ let expected_min_blob_epoch = current_epoch - blob_retention_epochs;
2698+ assert_eq ! (
2699+ Some ( expected_min_blob_epoch) ,
2700+ spec. min_epoch_data_availability_boundary( current_epoch)
2701+ ) ;
2702+ }
2703+
2704+ #[ test]
2705+ fn min_epochs_for_data_sidecar_requests_fulu ( ) {
2706+ type E = MainnetEthSpec ;
2707+ let spec = {
2708+ let mut spec = ForkName :: Deneb . make_genesis_spec ( E :: default_spec ( ) ) ;
2709+ // 4096 * 2 = 8192
2710+ spec. fulu_fork_epoch = Some ( Epoch :: new ( spec. min_epochs_for_blob_sidecars_requests * 2 ) ) ;
2711+ // set a different value for testing purpose, 4096 / 2 = 2048
2712+ spec. min_epochs_for_data_column_sidecars_requests =
2713+ spec. min_epochs_for_blob_sidecars_requests / 2 ;
2714+ Arc :: new ( spec)
2715+ } ;
2716+ let blob_retention_epochs = spec. min_epochs_for_blob_sidecars_requests ;
2717+ let data_column_retention_epochs = spec. min_epochs_for_data_column_sidecars_requests ;
2718+
2719+ // `min_epochs_for_data_sidecar_requests` at fulu fork epoch still uses `min_epochs_for_blob_sidecars_requests`
2720+ let fulu_fork_epoch = spec. fulu_fork_epoch . unwrap ( ) ;
2721+ let expected_blob_retention_epoch = fulu_fork_epoch - blob_retention_epochs;
2722+ assert_eq ! (
2723+ Some ( expected_blob_retention_epoch) ,
2724+ spec. min_epoch_data_availability_boundary( fulu_fork_epoch)
2725+ ) ;
2726+
2727+ // `min_epochs_for_data_sidecar_requests` at fulu fork epoch + min_epochs_for_blob_sidecars_request
2728+ let blob_retention_epoch_after_fulu = fulu_fork_epoch + blob_retention_epochs;
2729+ let expected_blob_retention_epoch = blob_retention_epoch_after_fulu - blob_retention_epochs;
2730+ assert_eq ! (
2731+ Some ( expected_blob_retention_epoch) ,
2732+ spec. min_epoch_data_availability_boundary( blob_retention_epoch_after_fulu)
2733+ ) ;
2734+
2735+ // After the final blob retention epoch, `min_epochs_for_data_sidecar_requests` should be calculated
2736+ // using `min_epochs_for_data_column_sidecars_request`
2737+ let current_epoch = blob_retention_epoch_after_fulu + 1 ;
2738+ let expected_data_column_retention_epoch = current_epoch - data_column_retention_epochs;
2739+ assert_eq ! (
2740+ Some ( expected_data_column_retention_epoch) ,
2741+ spec. min_epoch_data_availability_boundary( current_epoch)
2742+ ) ;
2743+ }
26522744}
0 commit comments