mithril_aggregator/services/signer_registration/
verifier.rs1use 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
15pub struct MithrilSignerRegistrationVerifier {
17 chain_observer: Arc<dyn ChainObserver>,
19}
20
21impl MithrilSignerRegistrationVerifier {
22 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}