mithril_aggregator/artifact_builder/
mithril_stake_distribution.rs

1use async_trait::async_trait;
2
3use super::ArtifactBuilder;
4use crate::dependency_injection::EpochServiceWrapper;
5use mithril_common::{
6    entities::{Certificate, Epoch, MithrilStakeDistribution},
7    StdResult,
8};
9
10/// A [MithrilStakeDistributionArtifact] builder
11pub struct MithrilStakeDistributionArtifactBuilder {
12    epoch_service: EpochServiceWrapper,
13}
14
15impl MithrilStakeDistributionArtifactBuilder {
16    /// MithrilStakeDistribution artifact builder factory
17    pub fn new(epoch_service: EpochServiceWrapper) -> Self {
18        Self { epoch_service }
19    }
20}
21
22#[async_trait]
23impl ArtifactBuilder<Epoch, MithrilStakeDistribution> for MithrilStakeDistributionArtifactBuilder {
24    async fn compute_artifact(
25        &self,
26        epoch: Epoch,
27        _certificate: &Certificate,
28    ) -> StdResult<MithrilStakeDistribution> {
29        let epoch_service = self.epoch_service.read().await;
30        let protocol_parameters = epoch_service.next_protocol_parameters()?;
31        Ok(MithrilStakeDistribution::new(
32            epoch,
33            epoch_service.next_signers_with_stake()?.clone(),
34            &protocol_parameters.clone(),
35        ))
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use mithril_common::{crypto_helper::ProtocolParameters, test_utils::fake_data};
42    use std::sync::Arc;
43    use tokio::sync::RwLock;
44
45    use super::*;
46
47    use crate::{entities::AggregatorEpochSettings, services::FakeEpochServiceBuilder};
48
49    #[tokio::test]
50    async fn should_compute_valid_artifact() {
51        let signers_with_stake = fake_data::signers_with_stakes(5);
52        let certificate = fake_data::certificate("certificate-123".to_string());
53        let epoch_settings = AggregatorEpochSettings {
54            protocol_parameters: fake_data::protocol_parameters(),
55            ..AggregatorEpochSettings::dummy()
56        };
57        let epoch_service = FakeEpochServiceBuilder {
58            current_epoch_settings: epoch_settings.clone(),
59            current_signers_with_stake: signers_with_stake.clone(),
60            next_signers_with_stake: signers_with_stake.clone(),
61            ..FakeEpochServiceBuilder::dummy(Epoch(1))
62        }
63        .build();
64        let mithril_stake_distribution_artifact_builder =
65            MithrilStakeDistributionArtifactBuilder::new(Arc::new(RwLock::new(epoch_service)));
66        let artifact = mithril_stake_distribution_artifact_builder
67            .compute_artifact(Epoch(1), &certificate)
68            .await
69            .unwrap();
70        let artifact_expected = MithrilStakeDistribution::new(
71            Epoch(1),
72            signers_with_stake,
73            &epoch_settings.protocol_parameters,
74        );
75        assert_eq!(artifact_expected, artifact);
76    }
77
78    #[test]
79    fn sort_given_signers_when_created() {
80        let signers_with_stake = fake_data::signers_with_stakes(5);
81
82        assert_eq!(
83            MithrilStakeDistribution::new(
84                Epoch(1),
85                signers_with_stake.clone(),
86                &ProtocolParameters {
87                    k: 1,
88                    m: 1,
89                    phi_f: 0.5
90                }
91                .into(),
92            ),
93            MithrilStakeDistribution::new(
94                Epoch(1),
95                signers_with_stake.into_iter().rev().collect(),
96                &ProtocolParameters {
97                    k: 1,
98                    m: 1,
99                    phi_f: 0.5
100                }
101                .into(),
102            )
103        );
104    }
105
106    #[test]
107    fn hash_value_doesnt_change_if_signers_order_change() {
108        let signers_with_stake = fake_data::signers_with_stakes(5);
109
110        let sd = MithrilStakeDistribution::new(
111            Epoch(1),
112            signers_with_stake.clone(),
113            &ProtocolParameters {
114                k: 1,
115                m: 1,
116                phi_f: 0.5,
117            }
118            .into(),
119        );
120        let sd2 = MithrilStakeDistribution::new(
121            Epoch(1),
122            signers_with_stake.into_iter().rev().collect(),
123            &ProtocolParameters {
124                k: 1,
125                m: 1,
126                phi_f: 0.5,
127            }
128            .into(),
129        );
130
131        assert_eq!(sd.hash, sd2.hash);
132    }
133}