@@ -129,11 +129,19 @@ impl MithrilCertificateChainSynchronizer {
129129 . with_context (
130130 || format ! ( "Failed to verify certificate: `{}`" , certificate. hash, ) ,
131131 ) ?;
132- validated_certificates. push_front ( certificate) ;
133132
134133 match parent_certificate {
135- None => break ,
134+ None => {
135+ validated_certificates. push_front ( certificate) ;
136+ break ;
137+ }
136138 Some ( parent) => {
139+ // At the start of the retrieval the first certificate may not be the first of
140+ // its epoch, filter them out since we only need one certificate per epoch
141+ if !validated_certificates. is_empty ( ) || parent. epoch != certificate. epoch {
142+ validated_certificates. push_front ( certificate) ;
143+ }
144+
137145 certificate = parent;
138146 }
139147 }
@@ -480,6 +488,8 @@ mod tests {
480488 mod retrieve_validate_remote_certificate_chain {
481489 use mockall:: predicate:: { always, eq} ;
482490
491+ use mithril_common:: entities:: Epoch ;
492+
483493 use super :: * ;
484494
485495 #[ tokio:: test]
@@ -512,10 +522,14 @@ mod tests {
512522 }
513523
514524 #[ tokio:: test]
515- async fn succeed_with_a_valid_certificate_chain ( ) {
525+ async fn succeed_with_a_valid_certificate_chain_and_only_get_first_certificate_of_each_epoch_plus_genesis ( )
526+ {
527+ // Note: the `CertificateChainBuilder` use one epoch for the genesis only, so in order
528+ // for the last epoch to have two certificates when `certificates_per_epoch` is an *even*
529+ // number, we need to set `total_certificates` to an *odd* number
516530 let chain = CertificateChainBuilder :: new ( )
517- . with_total_certificates ( 10 )
518- . with_certificates_per_epoch ( 3 )
531+ . with_total_certificates ( 9 )
532+ . with_certificates_per_epoch ( 2 )
519533 . build ( ) ;
520534 let synchroniser = MithrilCertificateChainSynchronizer {
521535 certificate_verifier : fake_verifier ( & chain) ,
@@ -530,21 +544,29 @@ mod tests {
530544 . unwrap ( ) ;
531545
532546 let mut expected = chain. certificate_path_to_genesis ( & starting_point. hash ) ;
547+ // Remote certificate chain is returned ordered from genesis to latest
533548 expected. reverse ( ) ;
549+ // Remove the latest certificate has it's not the first of its epoch
550+ expected. pop ( ) ;
534551 assert_eq ! ( remote_certificate_chain, expected) ;
535552 }
536553
537554 #[ tokio:: test]
538555 async fn return_chain_ordered_from_genesis_to_latest ( ) {
539556 let base_certificate = fake_data:: certificate ( "whatever" ) ;
540557 let chain = vec ! [
541- fake_data:: genesis_certificate( "genesis" ) ,
542558 Certificate {
559+ epoch: Epoch ( 2 ) ,
560+ ..fake_data:: genesis_certificate( "genesis" )
561+ } ,
562+ Certificate {
563+ epoch: Epoch ( 3 ) ,
543564 hash: "hash1" . to_string( ) ,
544565 previous_hash: "genesis" . to_string( ) ,
545566 ..base_certificate. clone( )
546567 } ,
547568 Certificate {
569+ epoch: Epoch ( 4 ) ,
548570 hash: "hash2" . to_string( ) ,
549571 previous_hash: "hash1" . to_string( ) ,
550572 ..base_certificate
0 commit comments