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: '{:?}'",
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}