mithril_aggregator/services/signer_registration/
verifier.rs

1use std::sync::Arc;
2
3use anyhow::{anyhow, Context};
4use async_trait::async_trait;
5
6use mithril_common::{
7    chain_observer::ChainObserver,
8    crypto_helper::{KESPeriod, ProtocolKeyRegistration},
9    entities::{Signer, SignerWithStake, StakeDistribution},
10    StdResult,
11};
12
13use super::SignerRegistrationVerifier;
14
15/// Implementation of a [SignerRegistrationVerifier]
16pub struct MithrilSignerRegistrationVerifier {
17    /// Chain observer service.
18    chain_observer: Arc<dyn ChainObserver>,
19}
20
21impl MithrilSignerRegistrationVerifier {
22    /// Creates a new [MithrilSignerRegistrationVerifier].
23    pub fn new(chain_observer: Arc<dyn ChainObserver>) -> Self {
24        Self { chain_observer }
25    }
26}
27
28#[async_trait]
29impl SignerRegistrationVerifier for MithrilSignerRegistrationVerifier {
30    async fn verify(
31        &self,
32        signer: &Signer,
33        stake_distribution: &StakeDistribution,
34    ) -> StdResult<SignerWithStake> {
35        let mut key_registration = ProtocolKeyRegistration::init(
36            &stake_distribution
37                .iter()
38                .map(|(k, v)| (k.to_owned(), *v))
39                .collect::<Vec<_>>(),
40        );
41        let party_id_register = match signer.party_id.as_str() {
42            "" => None,
43            party_id => Some(party_id.to_string()),
44        };
45        let kes_period = match &signer.operational_certificate {
46            Some(operational_certificate) => Some(
47                self.chain_observer
48                    .get_current_kes_period(operational_certificate)
49                    .await?
50                    .unwrap_or_default()
51                    - operational_certificate.start_kes_period as KESPeriod,
52            ),
53            None => None,
54        };
55        let party_id_registered = key_registration
56            .register(
57                party_id_register.clone(),
58                signer.operational_certificate.clone(),
59                signer.verification_key_signature,
60                kes_period,
61                signer.verification_key,
62            )
63            .with_context(|| {
64                format!(
65                    "KeyRegwrapper can not register signer with party_id: '{party_id_register:?}'"
66                )
67            })
68            .map_err(|e| anyhow!(e))?;
69        let party_id_registered_stake = *stake_distribution
70            .get(&party_id_registered)
71            .ok_or(anyhow!("Stake not found"))?;
72
73        Ok(SignerWithStake {
74            party_id: party_id_registered,
75            ..SignerWithStake::from_signer(signer.to_owned(), party_id_registered_stake)
76        })
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use mithril_common::{
83        chain_observer::FakeObserver, entities::TimePoint, test_utils::MithrilFixtureBuilder,
84    };
85
86    use super::*;
87
88    #[tokio::test]
89    async fn verify_succeeds_with_valid_signer_registration() {
90        let fixture = MithrilFixtureBuilder::default().with_signers(1).build();
91        let signer_to_register: Signer = fixture.signers()[0].to_owned();
92        let signer_registration_verifier = MithrilSignerRegistrationVerifier::new(Arc::new(
93            FakeObserver::new(Some(TimePoint::dummy())),
94        ));
95
96        signer_registration_verifier
97            .verify(&signer_to_register, &fixture.stake_distribution())
98            .await
99            .unwrap();
100    }
101
102    #[tokio::test]
103    async fn verify_fails_with_invalid_signer_registration() {
104        let fixture = MithrilFixtureBuilder::default().with_signers(2).build();
105        let signer_to_register: Signer = Signer {
106            verification_key_signature: fixture.signers()[1].verification_key_signature,
107            ..fixture.signers()[0].to_owned()
108        };
109        let signer_registration_verifier = MithrilSignerRegistrationVerifier::new(Arc::new(
110            FakeObserver::new(Some(TimePoint::dummy())),
111        ));
112
113        signer_registration_verifier
114            .verify(&signer_to_register, &fixture.stake_distribution())
115            .await
116            .expect_err("Verification should fail");
117    }
118}