@@ -50,6 +50,8 @@ cfg_fs! {
5050 pub missing: Vec <ImmutableFileName >,
5151 /// List of tampered immutable files.
5252 pub tampered: Vec <ImmutableFileName >,
53+ /// List of non-verifiable immutable files.
54+ pub non_verifiable: Vec <ImmutableFileName >,
5355 }
5456
5557 /// Compute Cardano database message related errors.
@@ -85,9 +87,8 @@ cfg_fs! {
8587 . join( "\n " )
8688 }
8789
88- let missing_files_subset = get_first_10_files_path( & lists. missing, & lists. immutables_dir) ;
89- let tampered_files_subset = get_first_10_files_path( & lists. tampered, & lists. immutables_dir) ;
9090 if !lists. missing. is_empty( ) {
91+ let missing_files_subset = get_first_10_files_path( & lists. missing, & lists. immutables_dir) ;
9192 writeln!(
9293 f,
9394 "Number of missing immutable files: {}" ,
@@ -100,10 +101,20 @@ cfg_fs! {
100101 writeln!( f) ?;
101102 }
102103 if !lists. tampered. is_empty( ) {
104+ let tampered_files_subset = get_first_10_files_path( & lists. tampered, & lists. immutables_dir) ;
103105 writeln!( f, "Number of tampered immutable files: {}" , lists. tampered. len( ) ) ?;
104106 writeln!( f, "First 10 tampered immutable files paths:" ) ?;
105107 writeln!( f, "{tampered_files_subset}" ) ?;
106108 }
109+ if ( !lists. missing. is_empty( ) || !lists. tampered. is_empty( ) ) && !lists. non_verifiable. is_empty( ) {
110+ writeln!( f) ?;
111+ }
112+ if !lists. non_verifiable. is_empty( ) {
113+ let non_verifiable_files_subset = get_first_10_files_path( & lists. non_verifiable, & lists. immutables_dir) ;
114+ writeln!( f, "Number of non verifiable immutable files: {}" , lists. non_verifiable. len( ) ) ?;
115+ writeln!( f, "First 10 non verifiable immutable files paths:" ) ?;
116+ writeln!( f, "{non_verifiable_files_subset}" ) ?;
117+ }
107118 Ok ( ( ) )
108119 }
109120 ComputeCardanoDatabaseMessageError :: ImmutableFilesDigester ( e) => {
@@ -269,20 +280,22 @@ impl MessageBuilder {
269280 return Ok ( message) ;
270281 }
271282
272- let tampered_files = match proof_result {
283+ let ( tampered , non_verifiable ) = match proof_result {
273284 Err ( e) => {
274285 warn!( self . logger, "{MERKLE_PROOF_COMPUTATION_ERROR}: {e:}" ) ;
275- verified_digests
276- . list_immutable_files_not_verified( & computed_digest_entries)
277- . tampered_files
286+ let verified_digests = verified_digests
287+ . list_immutable_files_not_verified( & computed_digest_entries) ;
288+
289+ ( verified_digests. tampered_files, verified_digests. non_verifiable_files)
278290 }
279- Ok ( _) => vec![ ] ,
291+ Ok ( _) => ( vec![ ] , vec! [ ] ) ,
280292 } ;
281293 Err (
282294 ComputeCardanoDatabaseMessageError :: ImmutableFilesVerification ( ImmutableFilesLists {
283295 immutables_dir: Self :: immutable_dir( database_dir) ,
284296 missing: missing_immutable_files,
285- tampered: tampered_files,
297+ tampered,
298+ non_verifiable,
286299 } ) ,
287300 )
288301 }
@@ -591,6 +604,7 @@ mod tests {
591604 immutables_dir: MessageBuilder :: immutable_dir( & database_dir) ,
592605 missing: to_vec_immutable_file_name( & files_to_remove) ,
593606 tampered: vec![ ] ,
607+ non_verifiable: vec![ ] ,
594608 }
595609 ) ;
596610 }
@@ -677,6 +691,7 @@ mod tests {
677691 immutables_dir: MessageBuilder :: immutable_dir( & database_dir) ,
678692 missing: vec![ ] ,
679693 tampered: to_vec_immutable_file_name( & files_to_tamper) ,
694+ non_verifiable: vec![ ] ,
680695 }
681696 )
682697 }
@@ -727,9 +742,77 @@ mod tests {
727742 immutables_dir: MessageBuilder :: immutable_dir( & database_dir) ,
728743 missing: to_vec_immutable_file_name( & files_to_remove) ,
729744 tampered: to_vec_immutable_file_name( & files_to_tamper) ,
745+ non_verifiable: vec![ ] ,
730746 }
731747 )
732748 }
749+
750+ #[ tokio:: test]
751+ async fn compute_cardano_database_message_should_fail_if_there_is_more_local_immutable_than_verified_digest ( )
752+ {
753+ let last_verified_digest_number = 10 ;
754+ let last_local_immutable_file_number = 15 ;
755+ let range_of_non_verifiable_files =
756+ last_verified_digest_number + 1 ..=last_local_immutable_file_number;
757+
758+ let expected_non_verifiable_files: Vec < ImmutableFileName > =
759+ ( range_of_non_verifiable_files)
760+ . flat_map ( |i| {
761+ [
762+ format ! ( "{i:05}.chunk" ) ,
763+ format ! ( "{i:05}.primary" ) ,
764+ format ! ( "{i:05}.secondary" ) ,
765+ ]
766+ } )
767+ . collect ( ) ;
768+
769+ let beacon = CardanoDbBeacon {
770+ epoch : Epoch ( 123 ) ,
771+ immutable_file_number : last_verified_digest_number,
772+ } ;
773+ //create verified digests for immutable files 1 to 10
774+ let ( _, certificate, verified_digests) = prepare_db_and_verified_digests (
775+ "database_dir_for_verified_digests" ,
776+ & beacon,
777+ & ( 1 ..=last_verified_digest_number) ,
778+ )
779+ . await ;
780+ //create a local database with immutable files 1 to 15
781+ let ( database_dir, _, _) = prepare_db_and_verified_digests (
782+ "database_dir_for_local_immutables" ,
783+ & beacon,
784+ & ( 1 ..=last_local_immutable_file_number) ,
785+ )
786+ . await ;
787+
788+ let error = MessageBuilder :: new ( )
789+ . compute_cardano_database_message (
790+ & certificate,
791+ & CardanoDatabaseSnapshotMessage :: dummy ( ) ,
792+ & ImmutableFileRange :: Range ( 1 , 15 ) ,
793+ false ,
794+ & database_dir,
795+ & verified_digests,
796+ )
797+ . await
798+ . expect_err (
799+ "compute_cardano_database_message should fail if there is more local immutable than verified digest" ,
800+ ) ;
801+
802+ let error_lists = match error {
803+ ComputeCardanoDatabaseMessageError :: ImmutableFilesVerification ( lists) => lists,
804+ _ => panic ! ( "Expected ImmutableFilesVerification error, got: {error}" ) ,
805+ } ;
806+ assert_eq ! (
807+ error_lists,
808+ ImmutableFilesLists {
809+ immutables_dir: MessageBuilder :: immutable_dir( & database_dir) ,
810+ missing: vec![ ] ,
811+ tampered: vec![ ] ,
812+ non_verifiable: expected_non_verifiable_files,
813+ }
814+ ) ;
815+ }
733816 }
734817
735818 mod compute_cardano_database_message_error {
@@ -738,6 +821,7 @@ mod tests {
738821 fn generate_immutable_files_verification_error (
739822 missing_range : Option < RangeInclusive < usize > > ,
740823 tampered_range : Option < RangeInclusive < usize > > ,
824+ non_verifiable_range : Option < RangeInclusive < usize > > ,
741825 immutable_path : & str ,
742826 ) -> ComputeCardanoDatabaseMessageError {
743827 let missing: Vec < ImmutableFileName > = match missing_range {
@@ -753,10 +837,18 @@ mod tests {
753837 None => vec ! [ ] ,
754838 } ;
755839
840+ let non_verifiable: Vec < ImmutableFileName > = match non_verifiable_range {
841+ Some ( range) => range
842+ . map ( |i| ImmutableFileName :: from ( format ! ( "{i:05}.chunk" ) ) )
843+ . collect ( ) ,
844+ None => vec ! [ ] ,
845+ } ;
846+
756847 ComputeCardanoDatabaseMessageError :: ImmutableFilesVerification ( ImmutableFilesLists {
757848 immutables_dir : PathBuf :: from ( immutable_path) ,
758849 missing,
759850 tampered,
851+ non_verifiable,
760852 } )
761853 }
762854
@@ -769,6 +861,7 @@ mod tests {
769861 let error = generate_immutable_files_verification_error (
770862 Some ( 1 ..=15 ) ,
771863 Some ( 20 ..=31 ) ,
864+ Some ( 40 ..=41 ) ,
772865 "/path/to/immutables" ,
773866 ) ;
774867
@@ -801,15 +894,21 @@ First 10 tampered immutable files paths:
801894/path/to/immutables/00027.chunk
802895/path/to/immutables/00028.chunk
803896/path/to/immutables/00029.chunk
897+
898+ Number of non verifiable immutable files: 2
899+ First 10 non verifiable immutable files paths:
900+ /path/to/immutables/00040.chunk
901+ /path/to/immutables/00041.chunk
804902"###
805903 ) ;
806904 }
807905
808906 #[ test]
809- fn display_immutable_files_should_not_display_error_list_if_missing_is_empty ( ) {
907+ fn display_immutable_files_should_display_tampered_files_only ( ) {
810908 let error = generate_immutable_files_verification_error (
811909 None ,
812910 Some ( 1 ..=1 ) ,
911+ None ,
813912 "/path/to/immutables" ,
814913 ) ;
815914
@@ -825,10 +924,11 @@ First 10 tampered immutable files paths:
825924 }
826925
827926 #[ test]
828- fn display_immutable_files_should_not_display_error_list_if_tampered_is_empty ( ) {
927+ fn display_immutable_files_should_display_missing_files_only ( ) {
829928 let error = generate_immutable_files_verification_error (
830929 Some ( 1 ..=1 ) ,
831930 None ,
931+ None ,
832932 "/path/to/immutables" ,
833933 ) ;
834934
@@ -839,6 +939,30 @@ First 10 tampered immutable files paths:
839939 r###"Number of missing immutable files: 1
840940First 10 missing immutable files paths:
841941/path/to/immutables/00001.chunk
942+ "###
943+ ) ;
944+ }
945+
946+ #[ test]
947+ fn display_immutable_files_should_display_non_verifiable_files_only ( ) {
948+ let error = generate_immutable_files_verification_error (
949+ None ,
950+ None ,
951+ Some ( 1 ..=5 ) ,
952+ "/path/to/immutables" ,
953+ ) ;
954+
955+ let display = normalize_path_separators ( & format ! ( "{error}" ) ) ;
956+
957+ assert_eq ! (
958+ display,
959+ r###"Number of non verifiable immutable files: 5
960+ First 10 non verifiable immutable files paths:
961+ /path/to/immutables/00001.chunk
962+ /path/to/immutables/00002.chunk
963+ /path/to/immutables/00003.chunk
964+ /path/to/immutables/00004.chunk
965+ /path/to/immutables/00005.chunk
842966"###
843967 ) ;
844968 }
0 commit comments