Skip to content

Commit 8fa4b49

Browse files
committed
feat: verify epoch value in certificate chain
1 parent 8bc56b1 commit 8fa4b49

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

mithril-aggregator/src/services/certifier/certifier_service.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,8 @@ mod tests {
717717
let network = fake_data::network();
718718
let beacon = CardanoDbBeacon::new(3, 1);
719719
let signed_entity_type = SignedEntityType::CardanoImmutableFilesFull(beacon.clone());
720-
let protocol_message = ProtocolMessage::new();
720+
let mut protocol_message = ProtocolMessage::new();
721+
protocol_message.set_message_part(ProtocolMessagePartKey::CurrentEpoch, "3".to_string());
721722
let epochs_with_signers = (1..=3).map(Epoch).collect::<Vec<_>>();
722723
let fixture = MithrilFixtureBuilder::default().with_signers(3).build();
723724
let certifier_service = setup_certifier_service_with_network(

mithril-common/src/certificate_chain/certificate_verifier.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ pub enum CertificateVerifierError {
5353
#[error("certificate chain AVK unmatch error")]
5454
CertificateChainAVKUnmatch,
5555

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+
5661
/// Error raised when validating the certificate chain if the chain loops.
5762
#[error("certificate chain infinite loop error")]
5863
CertificateChainInfiniteLoop,
@@ -206,6 +211,19 @@ impl MithrilCertificateVerifier {
206211

207212
Ok(())
208213
}
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+
}
209227
fn verify_aggregate_verification_key_chaining(
210228
&self,
211229
certificate: &Certificate,
@@ -270,6 +288,8 @@ impl CertificateVerifier for MithrilCertificateVerifier {
270288
genesis_signature,
271289
)
272290
.with_context(|| "Certificate verifier failed verifying a genesis certificate")?;
291+
self.verify_epoch_matches_protocol_message(genesis_certificate)?;
292+
273293
Ok(())
274294
}
275295

@@ -291,6 +311,7 @@ impl CertificateVerifier for MithrilCertificateVerifier {
291311
&certificate.aggregate_verification_key,
292312
&certificate.metadata.protocol_parameters,
293313
)?;
314+
self.verify_epoch_matches_protocol_message(certificate)?;
294315
self.verify_previous_hash_matches_previous_certificate_hash(
295316
certificate,
296317
previous_certificate,
@@ -532,6 +553,27 @@ mod tests {
532553
)
533554
}
534555

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+
535577
#[tokio::test]
536578
async fn verify_standard_certificate_success_with_different_epochs_as_previous() {
537579
let (total_certificates, certificates_per_epoch) = (5, 1);

0 commit comments

Comments
 (0)