@@ -815,3 +815,163 @@ mod test {
815815 ) ) ;
816816 }
817817}
818+
819+ #[ cfg( test) ]
820+ mod tests {
821+ use super :: * ;
822+ use crate :: kzg_utils:: blobs_to_data_column_sidecars;
823+ use crate :: test_utils:: BeaconChainHarness ;
824+ use std:: time:: Instant ;
825+ use types:: { ForkName , MainnetEthSpec } ;
826+
827+ fn measure_time < F > ( name : & str , f : F ) -> Result < ( ) , GossipDataColumnError >
828+ where
829+ F : FnOnce ( ) -> Result < ( ) , GossipDataColumnError > ,
830+ {
831+ let start = Instant :: now ( ) ;
832+ let result = f ( ) ;
833+ let duration = start. elapsed ( ) ;
834+ println ! ( "{}: {:?}" , name, duration) ;
835+ result
836+ }
837+
838+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 8 ) ]
839+ async fn test_data_column_validation_timing ( ) {
840+ // Setup the harness
841+ let spec = ForkName :: Fulu . make_genesis_spec ( MainnetEthSpec :: default_spec ( ) ) ;
842+ let harness = BeaconChainHarness :: builder ( MainnetEthSpec )
843+ . spec ( spec. into ( ) )
844+ . deterministic_keypairs ( 64 )
845+ . fresh_ephemeral_store ( )
846+ . mock_execution_layer ( )
847+ . build ( ) ;
848+
849+ harness. advance_slot ( ) ;
850+
851+ // Create a block with data columns
852+ let slot = harness. get_current_slot ( ) ;
853+ let state = harness. get_current_state ( ) ;
854+ let ( ( block, blobs) , _state) = harness. make_block ( state, slot) . await ;
855+
856+ // Create a data column sidecar
857+ let ( proofs, blobs) = blobs. unwrap ( ) ;
858+ println ! ( "blobs: {:?}" , blobs. len( ) ) ;
859+ let blob_refs = blobs. iter ( ) . collect :: < Vec < _ > > ( ) ;
860+ let column_sidecars = blobs_to_data_column_sidecars (
861+ & blob_refs,
862+ proofs. to_vec ( ) ,
863+ & block,
864+ & harness. chain . kzg ,
865+ & harness. chain . spec ,
866+ )
867+ . unwrap ( ) ;
868+
869+ // Measure each verification step
870+ let mut futures = vec ! [ ] ;
871+ for i in 0 ..8 {
872+ let column_sidecar = column_sidecars[ 0 ] . clone ( ) ;
873+ let chain = harness. chain . clone ( ) ;
874+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 100 ) ) . await ;
875+ futures. push ( tokio:: spawn ( async move {
876+ measure_time ( & format ! ( "verify_total_time_{}" , i) , || {
877+ Ok ( measure ( column_sidecar, & chain) )
878+ } )
879+ . expect ( "TODO: panic message" ) ;
880+ } ) ) ;
881+ }
882+ futures:: future:: join_all ( futures) . await ;
883+ }
884+
885+ fn measure < T : BeaconChainTypes > (
886+ column_sidecar : Arc < DataColumnSidecar < T :: EthSpec > > ,
887+ chain : & BeaconChain < T > ,
888+ ) {
889+ let result = {
890+ let column_slot = column_sidecar. slot ( ) ;
891+
892+ measure_time ( "verify_data_column_sidecar" , || {
893+ verify_data_column_sidecar ( & column_sidecar, & chain. spec )
894+ } )
895+ . unwrap ( ) ;
896+
897+ measure_time ( "verify_index_matches_subnet" , || {
898+ verify_index_matches_subnet ( & column_sidecar, column_sidecar. index , & chain. spec )
899+ } )
900+ . unwrap ( ) ;
901+
902+ measure_time ( "verify_sidecar_not_from_future_slot" , || {
903+ verify_sidecar_not_from_future_slot ( chain, column_slot)
904+ } )
905+ . unwrap ( ) ;
906+
907+ measure_time ( "verify_slot_greater_than_latest_finalized_slot" , || {
908+ verify_slot_greater_than_latest_finalized_slot ( chain, column_slot)
909+ } )
910+ . unwrap ( ) ;
911+
912+ measure_time ( "verify_is_first_sidecar" , || {
913+ verify_is_first_sidecar ( chain, & column_sidecar)
914+ } )
915+ . unwrap ( ) ;
916+
917+ measure_time ( "verify_column_inclusion_proof" , || {
918+ verify_column_inclusion_proof ( & column_sidecar)
919+ } )
920+ . unwrap ( ) ;
921+
922+ let mut parent_block = None ;
923+ measure_time ( "verify_parent_block_and_finalized_descendant" , || {
924+ parent_block = Some (
925+ verify_parent_block_and_finalized_descendant ( column_sidecar. clone ( ) , chain)
926+ . unwrap ( ) ,
927+ ) ;
928+ Ok ( ( ) )
929+ } )
930+ . unwrap ( ) ;
931+
932+ measure_time ( "verify_slot_higher_than_parent" , || {
933+ verify_slot_higher_than_parent ( parent_block. as_ref ( ) . unwrap ( ) , column_slot)
934+ } )
935+ . unwrap ( ) ;
936+
937+ measure_time ( "verify_proposer_and_signature" , || {
938+ verify_proposer_and_signature (
939+ & column_sidecar,
940+ parent_block. as_ref ( ) . unwrap ( ) ,
941+ chain,
942+ )
943+ } )
944+ . unwrap ( ) ;
945+
946+ let kzg = & chain. kzg ;
947+ measure_time ( "verify_kzg_for_data_column" , || {
948+ verify_kzg_for_data_column ( column_sidecar. clone ( ) , kzg) . unwrap ( ) ;
949+ Ok ( ( ) )
950+ } )
951+ . unwrap ( ) ;
952+
953+ measure_time ( "observe_slashable" , || {
954+ chain
955+ . observed_slashable
956+ . write ( )
957+ . observe_slashable (
958+ column_slot,
959+ column_sidecar. block_proposer_index ( ) ,
960+ column_sidecar. block_root ( ) ,
961+ )
962+ . unwrap ( ) ;
963+
964+ Ok ( ( ) )
965+ } )
966+ . unwrap ( ) ;
967+
968+ Ok :: < ( ) , GossipDataColumnError > ( ( ) )
969+ } ;
970+
971+ // Print overall result
972+ match result {
973+ Ok ( ( ) ) => println ! ( "All verifications passed successfully" ) ,
974+ Err ( e) => println ! ( "Verification failed: {:?}" , e) ,
975+ }
976+ }
977+ }
0 commit comments