@@ -7,15 +7,18 @@ use crate::aggregator::{AggregatorHandler, AggregatorHandlerError};
77use crate :: entities:: * ;
88use crate :: verifier:: { ProtocolError , Verifier } ;
99
10+ use mithril_common:: digesters:: { Digester , DigesterError , ImmutableDigester } ;
1011use mithril_common:: entities:: { Certificate , Snapshot } ;
11- use mithril_common:: immutable_digester:: { ImmutableDigester , ImmutableDigesterError } ;
1212
1313/// AggregatorHandlerWrapper wraps an AggregatorHandler
1414pub type AggregatorHandlerWrapper = Box < dyn AggregatorHandler > ;
1515
1616/// VerifierWrapper wraps a Verifier
1717pub type VerifierWrapper = Box < dyn Verifier > ;
1818
19+ /// DigesterWrapper wraps a Digester
20+ pub type DigesterWrapper = Box < dyn Digester > ;
21+
1922#[ derive( Error , Debug ) ]
2023pub enum RuntimeError {
2124 #[ error( "a dependency is missing: '{0}'" ) ]
@@ -31,7 +34,7 @@ pub enum RuntimeError {
3134 Verifier ( #[ from] ProtocolError ) ,
3235
3336 #[ error( "immutale digester error: '{0}'" ) ]
34- ImmutableDigester ( #[ from] ImmutableDigesterError ) ,
37+ ImmutableDigester ( #[ from] DigesterError ) ,
3538
3639 #[ error( "digest unmatch error: '{0}'" ) ]
3740 DigestUnmatch ( String ) ,
@@ -50,6 +53,9 @@ pub struct Runtime {
5053
5154 /// Verifier dependency that verifies certificates and their multi signatures
5255 verifier : Option < VerifierWrapper > ,
56+
57+ /// Digester dependency that computes the digest used as the message ot be signed and embedded in the multisignature
58+ digester : Option < DigesterWrapper > ,
5359}
5460
5561impl Runtime {
@@ -59,6 +65,7 @@ impl Runtime {
5965 network,
6066 aggregator_handler : None ,
6167 verifier : None ,
68+ digester : None ,
6269 }
6370 }
6471
@@ -77,6 +84,12 @@ impl Runtime {
7784 self
7885 }
7986
87+ /// With Digester
88+ pub fn with_digester ( & mut self , digester : DigesterWrapper ) -> & mut Self {
89+ self . digester = Some ( digester) ;
90+ self
91+ }
92+
8093 /// Get AggregatorHandler
8194 fn get_aggregator_handler ( & self ) -> Result < & AggregatorHandlerWrapper , RuntimeError > {
8295 self . aggregator_handler
@@ -91,6 +104,13 @@ impl Runtime {
91104 . ok_or_else ( || RuntimeError :: MissingDependency ( "verifier" . to_string ( ) ) )
92105 }
93106
107+ /// Get Digester
108+ fn get_digester ( & self ) -> Result < & DigesterWrapper , RuntimeError > {
109+ self . digester
110+ . as_ref ( )
111+ . ok_or_else ( || RuntimeError :: MissingDependency ( "digester" . to_string ( ) ) )
112+ }
113+
94114 /// List snapshots
95115 pub async fn list_snapshots ( & self ) -> Result < Vec < SnapshotListItem > , RuntimeError > {
96116 debug ! ( "List snapshots" ) ;
@@ -148,7 +168,7 @@ impl Runtime {
148168 }
149169
150170 /// Restore a snapshot by digest
151- pub async fn restore_snapshot ( & self , digest : & str ) -> Result < String , RuntimeError > {
171+ pub async fn restore_snapshot ( & mut self , digest : & str ) -> Result < String , RuntimeError > {
152172 debug ! ( "Restore snapshot {}" , digest) ;
153173 let snapshot = & self
154174 . get_aggregator_handler ( ) ?
@@ -178,11 +198,17 @@ impl Runtime {
178198 . unpack_snapshot ( digest)
179199 . await
180200 . map_err ( RuntimeError :: AggregatorHandler ) ?;
181- let unpacked_digest =
182- ImmutableDigester :: new ( Path :: new ( unpacked_path) . into ( ) , slog_scope:: logger ( ) )
183- . compute_digest ( )
184- . map_err ( RuntimeError :: ImmutableDigester ) ?
185- . digest ;
201+ if self . get_digester ( ) . is_err ( ) {
202+ self . with_digester ( Box :: new ( ImmutableDigester :: new (
203+ Path :: new ( unpacked_path) . into ( ) ,
204+ slog_scope:: logger ( ) ,
205+ ) ) ) ;
206+ }
207+ let unpacked_digest = self
208+ . get_digester ( ) ?
209+ . compute_digest ( )
210+ . map_err ( RuntimeError :: ImmutableDigester ) ?
211+ . digest ;
186212 match unpacked_digest == digest {
187213 true => Ok ( unpacked_path. to_owned ( ) ) ,
188214 false => Err ( RuntimeError :: DigestUnmatch ( unpacked_digest) ) ,
@@ -227,41 +253,20 @@ pub(crate) fn convert_to_field_items(
227253#[ cfg( test) ]
228254mod tests {
229255 use super :: * ;
256+ use mockall:: mock;
230257
231258 use crate :: aggregator:: { AggregatorHandlerError , MockAggregatorHandler } ;
232259 use crate :: verifier:: { MockVerifier , ProtocolError } ;
260+ use mithril_common:: digesters:: { Digester , DigesterError , DigesterResult } ;
233261 use mithril_common:: fake_data;
234262
235- // TODO: Dulicated test setup code from 'mithril-common/src/immutable_digester.rs' that maybe should be set in a `tests_setup' module in the 'immutable_digester'. A mock would be even better!
236- // Start duplicated code
237- use std:: fs;
238- use std:: fs:: File ;
239- use std:: io:: prelude:: * ;
240- use std:: path:: PathBuf ;
241- const ROOT_FOLDER : & str = "tests-work-folder/" ;
242-
243- fn get_test_dir ( subdir_name : & str ) -> PathBuf {
244- let parent_dir = format ! ( "{}{}" , ROOT_FOLDER , subdir_name) ;
245- let parent_dir = Path :: new ( & parent_dir) . to_path_buf ( ) ;
246-
247- if parent_dir. exists ( ) {
248- fs:: remove_dir_all ( & parent_dir)
249- . expect ( & * format ! ( "Could not remove dir {:?}" , parent_dir) ) ;
263+ mock ! {
264+ pub DigesterImpl { }
265+ impl Digester for DigesterImpl {
266+ fn compute_digest( & self ) -> Result <DigesterResult , DigesterError >;
250267 }
251- fs:: create_dir_all ( & parent_dir) . expect ( & * format ! ( "Could not create dir {:?}" , parent_dir) ) ;
252-
253- parent_dir
254268 }
255269
256- fn create_fake_files ( parent_dir : & Path , child_filenames : & [ & str ] ) {
257- for filename in child_filenames {
258- let file = parent_dir. join ( Path :: new ( filename) ) ;
259- let mut source_file = File :: create ( & file) . unwrap ( ) ;
260- write ! ( source_file, "This is a test file named '{}'" , filename) . unwrap ( ) ;
261- }
262- }
263- // End duplicated code
264-
265270 #[ tokio:: test]
266271 async fn test_list_snapshots_ok ( ) {
267272 let network = "testnet" . to_string ( ) ;
@@ -338,26 +343,14 @@ mod tests {
338343
339344 #[ tokio:: test]
340345 async fn test_restore_snapshot_ok ( ) {
341- let target_dir = get_test_dir ( "test_restore_snapshot_ok/immutable" ) ;
342- let entries = vec ! [
343- "001.chunk" ,
344- "001.primary" ,
345- "001.secondary" ,
346- "002.chunk" ,
347- "002.primary" ,
348- "002.secondary" ,
349- ] ;
350- create_fake_files ( & target_dir, & entries) ;
351- let digest = ImmutableDigester :: new ( target_dir. clone ( ) . into ( ) , slog_scope:: logger ( ) )
352- . compute_digest ( )
353- . unwrap ( )
354- . digest ;
346+ let digest = "digest123" ;
355347 let certificate_hash = "certhash123" ;
356348 let mut fake_certificate = fake_data:: certificate ( certificate_hash. to_string ( ) ) ;
357349 fake_certificate. hash = Certificate :: compute_hash ( & fake_certificate) ;
358350 let fake_snapshot = fake_data:: snapshots ( 1 ) . first ( ) . unwrap ( ) . to_owned ( ) ;
359351 let mut mock_aggregator_handler = MockAggregatorHandler :: new ( ) ;
360352 let mut mock_verifier = MockVerifier :: new ( ) ;
353+ let mut mock_digester = MockDigesterImpl :: new ( ) ;
361354 mock_aggregator_handler
362355 . expect_get_snapshot_details ( )
363356 . return_once ( move |_| Ok ( fake_snapshot) ) ;
@@ -366,14 +359,21 @@ mod tests {
366359 . return_once ( move |_| Ok ( fake_certificate) ) ;
367360 mock_aggregator_handler
368361 . expect_unpack_snapshot ( )
369- . return_once ( move |_| Ok ( target_dir . to_str ( ) . unwrap ( ) . to_owned ( ) ) ) ;
362+ . return_once ( move |_| Ok ( "./target-dir" . to_string ( ) ) ) ;
370363 mock_verifier
371364 . expect_verify_multi_signature ( )
372365 . return_once ( |_, _, _, _| Ok ( ( ) ) ) ;
366+ mock_digester. expect_compute_digest ( ) . return_once ( || {
367+ Ok ( DigesterResult {
368+ digest : digest. to_string ( ) ,
369+ last_immutable_file_number : 0 ,
370+ } )
371+ } ) ;
373372 let mut client = Runtime :: new ( "testnet" . to_string ( ) ) ;
374373 client
375374 . with_aggregator_handler ( Box :: new ( mock_aggregator_handler) )
376- . with_verifier ( Box :: new ( mock_verifier) ) ;
375+ . with_verifier ( Box :: new ( mock_verifier) )
376+ . with_digester ( Box :: new ( mock_digester) ) ;
377377 let restore = client. restore_snapshot ( & digest) . await ;
378378 restore. expect ( "unexpected error" ) ;
379379 }
@@ -386,38 +386,38 @@ mod tests {
386386 let fake_snapshot = fake_data:: snapshots ( 1 ) . first ( ) . unwrap ( ) . to_owned ( ) ;
387387 let mut mock_aggregator_handler = MockAggregatorHandler :: new ( ) ;
388388 let mock_verifier = MockVerifier :: new ( ) ;
389+ let mut mock_digester = MockDigesterImpl :: new ( ) ;
389390 mock_aggregator_handler
390391 . expect_get_snapshot_details ( )
391392 . return_once ( move |_| Ok ( fake_snapshot) ) ;
392393 mock_aggregator_handler
393394 . expect_get_certificate_details ( )
394395 . return_once ( move |_| Ok ( fake_certificate) ) ;
396+ mock_digester. expect_compute_digest ( ) . return_once ( || {
397+ Ok ( DigesterResult {
398+ digest : digest. to_string ( ) ,
399+ last_immutable_file_number : 0 ,
400+ } )
401+ } ) ;
395402 let mut client = Runtime :: new ( "testnet" . to_string ( ) ) ;
396403 client
397404 . with_aggregator_handler ( Box :: new ( mock_aggregator_handler) )
398- . with_verifier ( Box :: new ( mock_verifier) ) ;
405+ . with_verifier ( Box :: new ( mock_verifier) )
406+ . with_digester ( Box :: new ( mock_digester) ) ;
399407 let restore = client. restore_snapshot ( & digest) . await ;
400408 assert ! ( restore. is_err( ) , "an error should have occurred" ) ;
401409 }
402410
403411 #[ tokio:: test]
404412 async fn test_restore_snapshot_ko_digests_not_matching ( ) {
405- let target_dir = get_test_dir ( "test_restore_snapshot_ko_digests_not_matching/immutable" ) ;
406- let entries = vec ! [
407- "001.chunk" ,
408- "001.primary" ,
409- "001.secondary" ,
410- "002.chunk" ,
411- "002.primary" ,
412- "002.secondary" ,
413- ] ;
414- create_fake_files ( & target_dir, & entries) ;
415- let digest = "digest-not-matching" ;
413+ let digest = "digest123" ;
414+ let digest_tampered = "digest-not-matching" ;
416415 let certificate_hash = "certhash123" ;
417416 let fake_certificate = fake_data:: certificate ( certificate_hash. to_string ( ) ) ;
418417 let fake_snapshot = fake_data:: snapshots ( 1 ) . first ( ) . unwrap ( ) . to_owned ( ) ;
419418 let mut mock_aggregator_handler = MockAggregatorHandler :: new ( ) ;
420419 let mut mock_verifier = MockVerifier :: new ( ) ;
420+ let mut mock_digester = MockDigesterImpl :: new ( ) ;
421421 mock_aggregator_handler
422422 . expect_get_snapshot_details ( )
423423 . return_once ( move |_| Ok ( fake_snapshot) ) ;
@@ -426,27 +426,34 @@ mod tests {
426426 . return_once ( move |_| Ok ( fake_certificate) ) ;
427427 mock_aggregator_handler
428428 . expect_unpack_snapshot ( )
429- . return_once ( move |_| Ok ( target_dir . to_str ( ) . unwrap ( ) . to_owned ( ) ) ) ;
429+ . return_once ( move |_| Ok ( "./target-dir" . to_string ( ) ) ) ;
430430 mock_verifier
431431 . expect_verify_multi_signature ( )
432432 . return_once ( |_, _, _, _| Ok ( ( ) ) ) ;
433+ mock_digester. expect_compute_digest ( ) . return_once ( || {
434+ Ok ( DigesterResult {
435+ digest : digest_tampered. to_string ( ) ,
436+ last_immutable_file_number : 0 ,
437+ } )
438+ } ) ;
433439 let mut client = Runtime :: new ( "testnet" . to_string ( ) ) ;
434440 client
435441 . with_aggregator_handler ( Box :: new ( mock_aggregator_handler) )
436- . with_verifier ( Box :: new ( mock_verifier) ) ;
442+ . with_verifier ( Box :: new ( mock_verifier) )
443+ . with_digester ( Box :: new ( mock_digester) ) ;
437444 let restore = client. restore_snapshot ( digest) . await ;
438445 assert ! ( restore. is_err( ) , "an error should have occurred" ) ;
439446 }
440447
441448 #[ tokio:: test]
442449 async fn test_restore_snapshot_ko_digester_error ( ) {
443- let target_dir = get_test_dir ( "test_restore_snapshot_ko_digester_error/immutable" ) ;
444450 let digest = "digest123" ;
445451 let certificate_hash = "certhash123" ;
446452 let fake_certificate = fake_data:: certificate ( certificate_hash. to_string ( ) ) ;
447453 let fake_snapshot = fake_data:: snapshots ( 1 ) . first ( ) . unwrap ( ) . to_owned ( ) ;
448454 let mut mock_aggregator_handler = MockAggregatorHandler :: new ( ) ;
449455 let mut mock_verifier = MockVerifier :: new ( ) ;
456+ let mut mock_digester = MockDigesterImpl :: new ( ) ;
450457 mock_aggregator_handler
451458 . expect_get_snapshot_details ( )
452459 . return_once ( move |_| Ok ( fake_snapshot) ) ;
@@ -455,14 +462,18 @@ mod tests {
455462 . return_once ( move |_| Ok ( fake_certificate) ) ;
456463 mock_aggregator_handler
457464 . expect_unpack_snapshot ( )
458- . return_once ( move |_| Ok ( target_dir . to_str ( ) . unwrap ( ) . to_owned ( ) ) ) ;
465+ . return_once ( move |_| Ok ( "./target-dir" . to_string ( ) ) ) ;
459466 mock_verifier
460467 . expect_verify_multi_signature ( )
461468 . return_once ( |_, _, _, _| Ok ( ( ) ) ) ;
469+ mock_digester
470+ . expect_compute_digest ( )
471+ . return_once ( || Err ( DigesterError :: NotEnoughImmutable ( ) ) ) ;
462472 let mut client = Runtime :: new ( "testnet" . to_string ( ) ) ;
463473 client
464474 . with_aggregator_handler ( Box :: new ( mock_aggregator_handler) )
465- . with_verifier ( Box :: new ( mock_verifier) ) ;
475+ . with_verifier ( Box :: new ( mock_verifier) )
476+ . with_digester ( Box :: new ( mock_digester) ) ;
466477 let restore = client. restore_snapshot ( digest) . await ;
467478 assert ! ( restore. is_err( ) , "an error should have occurred" ) ;
468479 }
0 commit comments