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