@@ -129,11 +129,19 @@ impl MithrilCertificateChainSynchronizer {
129
129
. with_context (
130
130
|| format ! ( "Failed to verify certificate: `{}`" , certificate. hash, ) ,
131
131
) ?;
132
- validated_certificates. push_front ( certificate) ;
133
132
134
133
match parent_certificate {
135
- None => break ,
134
+ None => {
135
+ validated_certificates. push_front ( certificate) ;
136
+ break ;
137
+ }
136
138
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
+
137
145
certificate = parent;
138
146
}
139
147
}
@@ -480,6 +488,8 @@ mod tests {
480
488
mod retrieve_validate_remote_certificate_chain {
481
489
use mockall:: predicate:: { always, eq} ;
482
490
491
+ use mithril_common:: entities:: Epoch ;
492
+
483
493
use super :: * ;
484
494
485
495
#[ tokio:: test]
@@ -512,10 +522,14 @@ mod tests {
512
522
}
513
523
514
524
#[ 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
516
530
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 )
519
533
. build ( ) ;
520
534
let synchroniser = MithrilCertificateChainSynchronizer {
521
535
certificate_verifier : fake_verifier ( & chain) ,
@@ -530,21 +544,29 @@ mod tests {
530
544
. unwrap ( ) ;
531
545
532
546
let mut expected = chain. certificate_path_to_genesis ( & starting_point. hash ) ;
547
+ // Remote certificate chain is returned ordered from genesis to latest
533
548
expected. reverse ( ) ;
549
+ // Remove the latest certificate has it's not the first of its epoch
550
+ expected. pop ( ) ;
534
551
assert_eq ! ( remote_certificate_chain, expected) ;
535
552
}
536
553
537
554
#[ tokio:: test]
538
555
async fn return_chain_ordered_from_genesis_to_latest ( ) {
539
556
let base_certificate = fake_data:: certificate ( "whatever" ) ;
540
557
let chain = vec ! [
541
- fake_data:: genesis_certificate( "genesis" ) ,
542
558
Certificate {
559
+ epoch: Epoch ( 2 ) ,
560
+ ..fake_data:: genesis_certificate( "genesis" )
561
+ } ,
562
+ Certificate {
563
+ epoch: Epoch ( 3 ) ,
543
564
hash: "hash1" . to_string( ) ,
544
565
previous_hash: "genesis" . to_string( ) ,
545
566
..base_certificate. clone( )
546
567
} ,
547
568
Certificate {
569
+ epoch: Epoch ( 4 ) ,
548
570
hash: "hash2" . to_string( ) ,
549
571
previous_hash: "hash1" . to_string( ) ,
550
572
..base_certificate
0 commit comments