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    StdResult,
7    entities::{Certificate, Epoch, MithrilStakeDistribution},
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::{
42        crypto_helper::ProtocolParameters,
43        test::double::{Dummy, fake_data},
44    };
45    use std::sync::Arc;
46    use tokio::sync::RwLock;
47
48    use super::*;
49
50    use crate::{entities::AggregatorEpochSettings, services::FakeEpochServiceBuilder};
51
52    #[tokio::test]
53    async fn should_compute_valid_artifact() {
54        let signers_with_stake = fake_data::signers_with_stakes(5);
55        let certificate = fake_data::certificate("certificate-123".to_string());
56        let epoch_settings = AggregatorEpochSettings {
57            protocol_parameters: fake_data::protocol_parameters(),
58            ..AggregatorEpochSettings::dummy()
59        };
60        let epoch_service = FakeEpochServiceBuilder {
61            current_epoch_settings: epoch_settings.clone(),
62            current_signers_with_stake: signers_with_stake.clone(),
63            next_signers_with_stake: signers_with_stake.clone(),
64            ..FakeEpochServiceBuilder::dummy(Epoch(1))
65        }
66        .build();
67        let mithril_stake_distribution_artifact_builder =
68            MithrilStakeDistributionArtifactBuilder::new(Arc::new(RwLock::new(epoch_service)));
69        let artifact = mithril_stake_distribution_artifact_builder
70            .compute_artifact(Epoch(1), &certificate)
71            .await
72            .unwrap();
73        let artifact_expected = MithrilStakeDistribution::new(
74            Epoch(1),
75            signers_with_stake,
76            &epoch_settings.protocol_parameters,
77        );
78        assert_eq!(artifact_expected, artifact);
79    }
80
81    #[test]
82    fn sort_given_signers_when_created() {
83        let signers_with_stake = fake_data::signers_with_stakes(5);
84
85        assert_eq!(
86            MithrilStakeDistribution::new(
87                Epoch(1),
88                signers_with_stake.clone(),
89                &ProtocolParameters {
90                    k: 1,
91                    m: 1,
92                    phi_f: 0.5
93                }
94                .into(),
95            ),
96            MithrilStakeDistribution::new(
97                Epoch(1),
98                signers_with_stake.into_iter().rev().collect(),
99                &ProtocolParameters {
100                    k: 1,
101                    m: 1,
102                    phi_f: 0.5
103                }
104                .into(),
105            )
106        );
107    }
108
109    #[test]
110    fn hash_value_doesnt_change_if_signers_order_change() {
111        let signers_with_stake = fake_data::signers_with_stakes(5);
112
113        let sd = MithrilStakeDistribution::new(
114            Epoch(1),
115            signers_with_stake.clone(),
116            &ProtocolParameters {
117                k: 1,
118                m: 1,
119                phi_f: 0.5,
120            }
121            .into(),
122        );
123        let sd2 = MithrilStakeDistribution::new(
124            Epoch(1),
125            signers_with_stake.into_iter().rev().collect(),
126            &ProtocolParameters {
127                k: 1,
128                m: 1,
129                phi_f: 0.5,
130            }
131            .into(),
132        );
133
134        assert_eq!(sd.hash, sd2.hash);
135    }
136}