mithril_signer/services/chain_data/
preloader_checker.rs

1use std::sync::Arc;
2
3use anyhow::Context;
4use async_trait::async_trait;
5
6use mithril_common::{StdResult, entities::SignedEntityTypeDiscriminants};
7use mithril_protocol_config::interface::MithrilNetworkConfigurationProvider;
8use mithril_signed_entity_preloader::CardanoTransactionsPreloaderChecker;
9use mithril_ticker::TickerService;
10
11/// CardanoTransactionsPreloaderActivationSigner
12pub struct CardanoTransactionsPreloaderActivationSigner {
13    network_configuration_provider: Arc<dyn MithrilNetworkConfigurationProvider>,
14    ticker_service: Arc<dyn TickerService>,
15}
16
17impl CardanoTransactionsPreloaderActivationSigner {
18    /// Create a new instance of `CardanoTransactionsPreloaderActivationSigner`
19    pub fn new(
20        network_configuration_provider: Arc<dyn MithrilNetworkConfigurationProvider>,
21        ticker_service: Arc<dyn TickerService>,
22    ) -> Self {
23        Self {
24            network_configuration_provider,
25            ticker_service,
26        }
27    }
28}
29
30#[async_trait]
31impl CardanoTransactionsPreloaderChecker for CardanoTransactionsPreloaderActivationSigner {
32    async fn is_activated(&self) -> StdResult<bool> {
33        let epoch = self.ticker_service.get_current_epoch().await?;
34
35        let configuration = self
36            .network_configuration_provider
37            .get_network_configuration(epoch)
38            .await
39            .context(format!(
40                "An error occurred while retrieving Mithril network configuration for epoch {epoch}"
41            ))?;
42
43        let activated_signed_entity_types = configuration
44            .configuration_for_aggregation
45            .enabled_signed_entity_types;
46
47        let next_activated_signed_entity_types = configuration
48            .configuration_for_next_aggregation
49            .enabled_signed_entity_types;
50
51        Ok(activated_signed_entity_types
52            .union(&next_activated_signed_entity_types)
53            .any(|s| s == &SignedEntityTypeDiscriminants::CardanoTransactions))
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use anyhow::anyhow;
60    use mithril_common::{
61        entities::{Epoch, SignedEntityTypeDiscriminants, TimePoint},
62        test::double::Dummy,
63    };
64    use mithril_protocol_config::model::{
65        MithrilNetworkConfiguration, MithrilNetworkConfigurationForEpoch,
66    };
67    use mockall::mock;
68    use std::collections::BTreeSet;
69
70    use super::*;
71
72    mock! {
73        pub MithrilNetworkConfigurationProvider {}
74
75        #[async_trait]
76        impl MithrilNetworkConfigurationProvider for MithrilNetworkConfigurationProvider {
77            async fn get_network_configuration(&self, epoch: Epoch) -> StdResult<MithrilNetworkConfiguration>;
78        }
79    }
80    mock! {
81        pub TickerService {}
82
83        #[async_trait]
84        impl TickerService for TickerService {
85            async fn get_current_time_point(&self) -> StdResult<TimePoint>;
86            async fn get_current_epoch(&self) -> StdResult<Epoch>;
87        }
88    }
89
90    #[tokio::test]
91    async fn preloader_activation_is_not_activated_when_cardano_transactions_not_in_current_or_next_configuration_for_aggregation()
92     {
93        let mut network_configuration_provider = MockMithrilNetworkConfigurationProvider::new();
94        network_configuration_provider
95            .expect_get_network_configuration()
96            .times(1)
97            .returning(|_| {
98                Ok(MithrilNetworkConfiguration {
99                    configuration_for_aggregation: MithrilNetworkConfigurationForEpoch {
100                        enabled_signed_entity_types: BTreeSet::from([]),
101                        ..Dummy::dummy()
102                    },
103                    configuration_for_next_aggregation: MithrilNetworkConfigurationForEpoch {
104                        enabled_signed_entity_types: BTreeSet::from([]),
105                        ..Dummy::dummy()
106                    },
107                    ..Dummy::dummy()
108                })
109            });
110        let mut ticker_service = MockTickerService::new();
111        ticker_service
112            .expect_get_current_epoch()
113            .times(1)
114            .returning(|| Ok(Epoch(1)));
115
116        let preloader = CardanoTransactionsPreloaderActivationSigner::new(
117            Arc::new(network_configuration_provider),
118            Arc::new(ticker_service),
119        );
120
121        let is_activated = preloader.is_activated().await.unwrap();
122
123        assert!(!is_activated);
124    }
125
126    #[tokio::test]
127    async fn preloader_activation_is_activated_when_cardano_transactions_is_in_configuration_for_aggregation()
128     {
129        let mut network_configuration_provider = MockMithrilNetworkConfigurationProvider::new();
130        network_configuration_provider
131            .expect_get_network_configuration()
132            .times(1)
133            .returning(|_| {
134                Ok(MithrilNetworkConfiguration {
135                    configuration_for_aggregation: MithrilNetworkConfigurationForEpoch {
136                        enabled_signed_entity_types: BTreeSet::from([
137                            SignedEntityTypeDiscriminants::CardanoTransactions,
138                        ]),
139                        ..Dummy::dummy()
140                    },
141                    configuration_for_next_aggregation: MithrilNetworkConfigurationForEpoch {
142                        enabled_signed_entity_types: BTreeSet::from([]),
143                        ..Dummy::dummy()
144                    },
145                    ..Dummy::dummy()
146                })
147            });
148
149        let mut ticker_service = MockTickerService::new();
150        ticker_service
151            .expect_get_current_epoch()
152            .times(1)
153            .returning(|| Ok(Epoch(1)));
154
155        let preloader = CardanoTransactionsPreloaderActivationSigner::new(
156            Arc::new(network_configuration_provider),
157            Arc::new(ticker_service),
158        );
159
160        let is_activated = preloader.is_activated().await.unwrap();
161
162        assert!(is_activated);
163    }
164
165    #[tokio::test]
166    async fn preloader_activation_is_activated_when_cardano_transactions_is_in_configuration_for_next_aggregation()
167     {
168        let mut network_configuration_provider = MockMithrilNetworkConfigurationProvider::new();
169        network_configuration_provider
170            .expect_get_network_configuration()
171            .times(1)
172            .returning(|_| {
173                Ok(MithrilNetworkConfiguration {
174                    configuration_for_aggregation: MithrilNetworkConfigurationForEpoch {
175                        enabled_signed_entity_types: BTreeSet::from([]),
176                        ..Dummy::dummy()
177                    },
178                    configuration_for_next_aggregation: MithrilNetworkConfigurationForEpoch {
179                        enabled_signed_entity_types: BTreeSet::from([
180                            SignedEntityTypeDiscriminants::CardanoTransactions,
181                        ]),
182                        ..Dummy::dummy()
183                    },
184                    ..Dummy::dummy()
185                })
186            });
187
188        let mut ticker_service = MockTickerService::new();
189        ticker_service
190            .expect_get_current_epoch()
191            .times(1)
192            .returning(|| Ok(Epoch(1)));
193
194        let preloader = CardanoTransactionsPreloaderActivationSigner::new(
195            Arc::new(network_configuration_provider),
196            Arc::new(ticker_service),
197        );
198
199        let is_activated = preloader.is_activated().await.unwrap();
200
201        assert!(is_activated);
202    }
203
204    #[tokio::test]
205    async fn preloader_activation_state_activate_preloader_when_aggregator_call_fails() {
206        let mut network_configuration_provider = MockMithrilNetworkConfigurationProvider::new();
207        network_configuration_provider
208            .expect_get_network_configuration()
209            .times(1)
210            .returning(|_| Err(anyhow!("Aggregator call failure")));
211
212        let mut ticker_service = MockTickerService::new();
213        ticker_service
214            .expect_get_current_epoch()
215            .times(1)
216            .returning(|| Ok(Epoch(1)));
217
218        let preloader = CardanoTransactionsPreloaderActivationSigner::new(
219            Arc::new(network_configuration_provider),
220            Arc::new(ticker_service),
221        );
222
223        preloader
224            .is_activated()
225            .await
226            .expect_err("Should fail due to aggregator call failure");
227    }
228
229    #[tokio::test]
230    async fn preloader_activation_state_activate_preloader_when_ticker_service_call_fails() {
231        let network_configuration_provider = MockMithrilNetworkConfigurationProvider::new();
232
233        let mut ticker_service = MockTickerService::new();
234        ticker_service
235            .expect_get_current_epoch()
236            .times(1)
237            .returning(|| Err(anyhow!("Ticker service call failure")));
238
239        let preloader = CardanoTransactionsPreloaderActivationSigner::new(
240            Arc::new(network_configuration_provider),
241            Arc::new(ticker_service),
242        );
243
244        preloader
245            .is_activated()
246            .await
247            .expect_err("Should fail due to ticker service call failure");
248    }
249}