@@ -644,8 +644,17 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
644644 "Reconstructed columns"
645645 ) ;
646646
647+ let columns_to_sample = self
648+ . custody_context ( )
649+ . sampling_columns_for_epoch ( slot. epoch ( T :: EthSpec :: slots_per_epoch ( ) ) , & self . spec ) ;
650+ let data_columns_to_import: Vec < _ > = data_columns_to_publish
651+ . iter ( )
652+ . filter ( |column| columns_to_sample. contains ( & column. index ( ) ) )
653+ . cloned ( )
654+ . collect ( ) ;
655+
647656 self . availability_cache
648- . put_kzg_verified_data_columns ( * block_root, data_columns_to_publish . clone ( ) )
657+ . put_kzg_verified_data_columns ( * block_root, data_columns_to_import )
649658 . map ( |availability| {
650659 DataColumnReconstructionResult :: Success ( (
651660 availability,
@@ -1082,6 +1091,95 @@ mod test {
10821091 verification_result. expect_err ( "should have failed to verify blocks" ) ;
10831092 }
10841093
1094+ #[ test]
1095+ fn should_exclude_reconstructed_columns_not_required_for_sampling ( ) {
1096+ // SETUP
1097+ let spec = Arc :: new ( ForkName :: Fulu . make_genesis_spec ( E :: default_spec ( ) ) ) ;
1098+ let mut rng = StdRng :: seed_from_u64 ( 0xDEADBEEF0BAD5EEDu64 ) ;
1099+
1100+ let da_checker = new_da_checker ( spec. clone ( ) ) ;
1101+ let custody_context = & da_checker. custody_context ;
1102+ let all_column_indices_ordered =
1103+ init_custody_context_with_ordered_columns ( custody_context, & mut rng, & spec) ;
1104+
1105+ // Set custody requirement to 65 columns (enough to trigger reconstruction)
1106+ let epoch = Epoch :: new ( 1 ) ;
1107+ custody_context. register_validators (
1108+ vec ! [ ( 0 , 2_048_000_000_000 ) , ( 1 , 32_000_000_000 ) ] , // 64 + 1
1109+ Slot :: new ( 0 ) ,
1110+ & spec,
1111+ ) ;
1112+ let sampling_requirement = custody_context. num_of_data_columns_to_sample ( epoch, & spec) ;
1113+ assert_eq ! (
1114+ sampling_requirement, 65 ,
1115+ "sampling requirement should be 65"
1116+ ) ;
1117+
1118+ let ( block, data_columns) = generate_rand_block_and_data_columns :: < E > (
1119+ ForkName :: Fulu ,
1120+ NumBlobs :: Number ( 1 ) ,
1121+ & mut rng,
1122+ & spec,
1123+ ) ;
1124+ let block_root = Hash256 :: random ( ) ;
1125+ // Add the block to the DA checker
1126+ da_checker
1127+ . availability_cache
1128+ . put_pre_execution_block ( block_root, Arc :: new ( block) , BlockImportSource :: Gossip )
1129+ . expect ( "should put block" ) ;
1130+
1131+ // Add 64 columns to the da checker (enough to be able to reconstruct)
1132+ // Order by all_column_indices_ordered, then take first 64
1133+ let custody_columns = all_column_indices_ordered
1134+ . iter ( )
1135+ . filter_map ( |& col_idx| data_columns. iter ( ) . find ( |d| d. index == col_idx) . cloned ( ) )
1136+ . take ( 64 )
1137+ . map ( |d| {
1138+ KzgVerifiedCustodyDataColumn :: from_asserted_custody (
1139+ KzgVerifiedDataColumn :: __new_for_testing ( d) ,
1140+ )
1141+ } )
1142+ . collect :: < Vec < _ > > ( ) ;
1143+
1144+ da_checker
1145+ . availability_cache
1146+ . put_kzg_verified_data_columns ( block_root, custody_columns)
1147+ . expect ( "should put custody columns" ) ;
1148+
1149+ // Try reconstrucing
1150+ let reconstruction_result = da_checker
1151+ . reconstruct_data_columns ( & block_root)
1152+ . expect ( "should reconstruct columns" ) ;
1153+
1154+ // Reconstruction should succeed
1155+ let ( _availability, reconstructed_columns) = match reconstruction_result {
1156+ DataColumnReconstructionResult :: Success ( result) => result,
1157+ e => {
1158+ panic ! ( "Expected successful reconstruction {:?}" , e) ;
1159+ }
1160+ } ;
1161+
1162+ // Remaining 64 columns should be reconstructed
1163+ assert_eq ! (
1164+ reconstructed_columns. len( ) ,
1165+ 64 ,
1166+ "should reconstruct the remaining 64 columns"
1167+ ) ;
1168+
1169+ // Only the columns required for custody (65) should be imported into the cache
1170+ let sampling_columns = custody_context. sampling_columns_for_epoch ( epoch, & spec) ;
1171+ let actual_cached: HashSet < ColumnIndex > = da_checker
1172+ . cached_data_column_indexes ( & block_root)
1173+ . expect ( "should have cached data columns" )
1174+ . into_iter ( )
1175+ . collect ( ) ;
1176+ let expected_sampling_columns = sampling_columns. iter ( ) . copied ( ) . collect :: < HashSet < _ > > ( ) ;
1177+ assert_eq ! (
1178+ actual_cached, expected_sampling_columns,
1179+ "should cache only the required custody columns, not all reconstructed columns"
1180+ ) ;
1181+ }
1182+
10851183 fn init_custody_context_with_ordered_columns (
10861184 custody_context : & Arc < CustodyContext < E > > ,
10871185 mut rng : & mut StdRng ,
0 commit comments