@@ -53,6 +53,11 @@ pub enum CertificateVerifierError {
53
53
#[ error( "certificate chain AVK unmatch error" ) ]
54
54
CertificateChainAVKUnmatch ,
55
55
56
+ /// Error raised when validating the certificate chain if the current [Certificate]
57
+ /// `epoch` doesn't match the signed `current_epoch` of the current certificate
58
+ #[ error( "certificate epoch unmatch error" ) ]
59
+ CertificateEpochUnmatch ,
60
+
56
61
/// Error raised when validating the certificate chain if the chain loops.
57
62
#[ error( "certificate chain infinite loop error" ) ]
58
63
CertificateChainInfiniteLoop ,
@@ -206,6 +211,19 @@ impl MithrilCertificateVerifier {
206
211
207
212
Ok ( ( ) )
208
213
}
214
+
215
+ fn verify_epoch_matches_protocol_message ( & self , certificate : & Certificate ) -> StdResult < ( ) > {
216
+ if let Some ( signed_epoch) = & certificate
217
+ . protocol_message
218
+ . get_message_part ( & ProtocolMessagePartKey :: CurrentEpoch )
219
+ {
220
+ if * * signed_epoch == certificate. epoch . to_string ( ) {
221
+ return Ok ( ( ) ) ;
222
+ }
223
+ }
224
+
225
+ Err ( anyhow ! ( CertificateVerifierError :: CertificateEpochUnmatch ) )
226
+ }
209
227
fn verify_aggregate_verification_key_chaining (
210
228
& self ,
211
229
certificate : & Certificate ,
@@ -270,6 +288,8 @@ impl CertificateVerifier for MithrilCertificateVerifier {
270
288
genesis_signature,
271
289
)
272
290
. with_context ( || "Certificate verifier failed verifying a genesis certificate" ) ?;
291
+ self . verify_epoch_matches_protocol_message ( genesis_certificate) ?;
292
+
273
293
Ok ( ( ) )
274
294
}
275
295
@@ -291,6 +311,7 @@ impl CertificateVerifier for MithrilCertificateVerifier {
291
311
& certificate. aggregate_verification_key ,
292
312
& certificate. metadata . protocol_parameters ,
293
313
) ?;
314
+ self . verify_epoch_matches_protocol_message ( certificate) ?;
294
315
self . verify_previous_hash_matches_previous_certificate_hash (
295
316
certificate,
296
317
previous_certificate,
@@ -532,6 +553,27 @@ mod tests {
532
553
)
533
554
}
534
555
556
+ #[ tokio:: test]
557
+ async fn verify_genesis_certificate_fails_if_epoch_unmatch ( ) {
558
+ let ( total_certificates, certificates_per_epoch) = ( 5 , 1 ) ;
559
+ let ( fake_certificates, genesis_verifier) =
560
+ setup_certificate_chain ( total_certificates, certificates_per_epoch) ;
561
+ let verifier = MockDependencyInjector :: new ( ) . build_certificate_verifier ( ) ;
562
+ let mut genesis_certificate = fake_certificates. last ( ) . unwrap ( ) . clone ( ) ;
563
+ genesis_certificate. epoch -= 1 ;
564
+ genesis_certificate. hash = genesis_certificate. compute_hash ( ) ;
565
+
566
+ let error = verifier
567
+ . verify_genesis_certificate (
568
+ & genesis_certificate,
569
+ & genesis_verifier. to_verification_key ( ) ,
570
+ )
571
+ . await
572
+ . expect_err ( "verify_genesis_certificate should fail" ) ;
573
+
574
+ assert_error_matches ! ( CertificateVerifierError :: CertificateEpochUnmatch , error)
575
+ }
576
+
535
577
#[ tokio:: test]
536
578
async fn verify_standard_certificate_success_with_different_epochs_as_previous ( ) {
537
579
let ( total_certificates, certificates_per_epoch) = ( 5 , 1 ) ;
0 commit comments