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: '{:?}'",
66                    party_id_register
67                )
68            })
69            .map_err(|e| anyhow!(e))?;
70        let party_id_registered_stake = *stake_distribution
71            .get(&party_id_registered)
72            .ok_or(anyhow!("Stake not found"))?;
73
74        Ok(SignerWithStake {
75            party_id: party_id_registered,
76            ..SignerWithStake::from_signer(signer.to_owned(), party_id_registered_stake)
77        })
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use mithril_common::{
84        chain_observer::FakeObserver, entities::TimePoint, test_utils::MithrilFixtureBuilder,
85    };
86
87    use super::*;
88
89    #[tokio::test]
90    async fn verify_succeeds_with_valid_signer_registration() {
91        let fixture = MithrilFixtureBuilder::default().with_signers(1).build();
92        let signer_to_register: Signer = fixture.signers()[0].to_owned();
93        let signer_registration_verifier = MithrilSignerRegistrationVerifier::new(Arc::new(
94            FakeObserver::new(Some(TimePoint::dummy())),
95        ));
96
97        signer_registration_verifier
98            .verify(&signer_to_register, &fixture.stake_distribution())
99            .await
100            .unwrap();
101    }
102
103    #[tokio::test]
104    async fn verify_fails_with_invalid_signer_registration() {
105        let fixture = MithrilFixtureBuilder::default().with_signers(2).build();
106        let signer_to_register: Signer = Signer {
107            verification_key_signature: fixture.signers()[1].verification_key_signature,
108            ..fixture.signers()[0].to_owned()
109        };
110        let signer_registration_verifier = MithrilSignerRegistrationVerifier::new(Arc::new(
111            FakeObserver::new(Some(TimePoint::dummy())),
112        ));
113
114        signer_registration_verifier
115            .verify(&signer_to_register, &fixture.stake_distribution())
116            .await
117            .expect_err("Verification should fail");
118    }
119}