mithril_aggregator/services/
network_configuration_provider.rs1use anyhow::Context;
2use async_trait::async_trait;
3use std::collections::BTreeSet;
4use std::sync::Arc;
5
6use mithril_common::StdResult;
7use mithril_common::entities::{Epoch, SignedEntityTypeDiscriminants};
8use mithril_protocol_config::interface::MithrilNetworkConfigurationProvider;
9use mithril_protocol_config::model::{
10 MithrilNetworkConfiguration, MithrilNetworkConfigurationForEpoch, SignedEntityTypeConfiguration,
11};
12
13use crate::EpochSettingsStorer;
14use crate::entities::AggregatorEpochSettings;
15
16pub struct LocalMithrilNetworkConfigurationProvider {
19 local_configuration_epoch_settings: AggregatorEpochSettings,
20 allowed_discriminants: BTreeSet<SignedEntityTypeDiscriminants>,
21 epoch_settings_store: Arc<dyn EpochSettingsStorer>,
22}
23
24impl LocalMithrilNetworkConfigurationProvider {
25 pub fn new(
27 local_configuration_epoch_settings: AggregatorEpochSettings,
28 allowed_discriminants: BTreeSet<SignedEntityTypeDiscriminants>,
29 epoch_settings_store: Arc<dyn EpochSettingsStorer>,
30 ) -> Self {
31 Self {
32 local_configuration_epoch_settings,
33 allowed_discriminants,
34 epoch_settings_store,
35 }
36 }
37
38 async fn get_stored_configuration_or_fallback(
40 &self,
41 epoch: Epoch,
42 ) -> StdResult<MithrilNetworkConfigurationForEpoch> {
43 let epoch_settings = self.epoch_settings_store.get_epoch_settings(epoch).await?.unwrap_or(
44 AggregatorEpochSettings {
45 protocol_parameters: self
46 .local_configuration_epoch_settings
47 .protocol_parameters
48 .clone(),
49 cardano_transactions_signing_config: self
50 .local_configuration_epoch_settings
51 .cardano_transactions_signing_config
52 .clone(),
53 },
54 );
55
56 Ok(MithrilNetworkConfigurationForEpoch {
57 enabled_signed_entity_types: self.allowed_discriminants.clone(),
58 protocol_parameters: epoch_settings.protocol_parameters,
59 signed_entity_types_config: SignedEntityTypeConfiguration {
60 cardano_transactions: epoch_settings.cardano_transactions_signing_config,
61 },
62 })
63 }
64}
65
66#[async_trait]
67impl MithrilNetworkConfigurationProvider for LocalMithrilNetworkConfigurationProvider {
68 async fn get_network_configuration(
69 &self,
70 epoch: Epoch,
71 ) -> StdResult<MithrilNetworkConfiguration> {
72 let aggregation_epoch =
73 epoch.offset_to_signer_retrieval_epoch().with_context(|| {
74 format!("MithrilNetworkConfigurationProvider could not compute aggregation epoch from epoch: {epoch}")
75 })?;
76 let next_aggregation_epoch = epoch.offset_to_next_signer_retrieval_epoch();
77 let registration_epoch = epoch.offset_to_next_signer_retrieval_epoch().next();
78
79 let configuration_for_aggregation =
80 self.get_stored_configuration_or_fallback(aggregation_epoch).await?;
81 let configuration_for_next_aggregation = self
82 .get_stored_configuration_or_fallback(next_aggregation_epoch)
83 .await?;
84 let configuration_for_registration =
85 self.get_stored_configuration_or_fallback(registration_epoch).await?;
86
87 let config = MithrilNetworkConfiguration {
88 epoch,
89 configuration_for_aggregation,
90 configuration_for_next_aggregation,
91 configuration_for_registration,
92 };
93 Ok(config)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use mithril_common::{
100 entities::{BlockNumber, CardanoTransactionsSigningConfig, ProtocolParameters},
101 test::double::Dummy,
102 };
103
104 use crate::store::FakeEpochSettingsStorer;
105
106 use super::*;
107
108 #[tokio::test]
109 async fn get_stored_configuration_with_stored_value_returns_them() {
110 let local_configuration_epoch_settings = AggregatorEpochSettings {
111 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
112 ..Dummy::dummy()
113 };
114 let stored_epoch_settings = AggregatorEpochSettings {
115 protocol_parameters: ProtocolParameters::new(1000, 100, 0.1),
116 ..Dummy::dummy()
117 };
118
119 let local_provider = LocalMithrilNetworkConfigurationProvider::new(
120 local_configuration_epoch_settings,
121 SignedEntityTypeDiscriminants::all(),
122 Arc::new(FakeEpochSettingsStorer::new(vec![(
123 Epoch(42),
124 stored_epoch_settings.clone(),
125 )])),
126 );
127
128 let network_configuration = local_provider
129 .get_stored_configuration_or_fallback(Epoch(42))
130 .await
131 .unwrap();
132
133 assert_eq!(
134 stored_epoch_settings.protocol_parameters,
135 network_configuration.protocol_parameters
136 )
137 }
138
139 #[tokio::test]
140 async fn get_stored_configuration_without_stored_value_fallback_to_configuration_value() {
141 let local_configuration_epoch_settings = AggregatorEpochSettings {
142 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
143 ..Dummy::dummy()
144 };
145
146 let local_provider = LocalMithrilNetworkConfigurationProvider::new(
147 local_configuration_epoch_settings.clone(),
148 SignedEntityTypeDiscriminants::all(),
149 Arc::new(FakeEpochSettingsStorer::new(vec![])),
150 );
151
152 let network_configuration = local_provider
153 .get_stored_configuration_or_fallback(Epoch(42))
154 .await
155 .unwrap();
156
157 assert_eq!(
158 local_configuration_epoch_settings.protocol_parameters,
159 network_configuration.protocol_parameters
160 )
161 }
162
163 #[tokio::test]
164 async fn test_get_network_configuration_retrieve_configurations_for_aggregation_next_aggregation_and_registration()
165 {
166 let local_configuration_epoch_settings = AggregatorEpochSettings {
167 protocol_parameters: ProtocolParameters::new(3000, 300, 0.3),
168 cardano_transactions_signing_config: Some(CardanoTransactionsSigningConfig {
169 security_parameter: BlockNumber(3),
170 step: BlockNumber(30),
171 }),
172 };
173
174 let local_provider = LocalMithrilNetworkConfigurationProvider::new(
176 local_configuration_epoch_settings,
177 SignedEntityTypeDiscriminants::all(),
178 Arc::new(FakeEpochSettingsStorer::new(vec![
179 (
180 Epoch(42),
181 AggregatorEpochSettings {
182 protocol_parameters: ProtocolParameters::new(1000, 100, 0.1),
183 cardano_transactions_signing_config: Some(
184 CardanoTransactionsSigningConfig {
185 security_parameter: BlockNumber(1),
186 step: BlockNumber(10),
187 },
188 ),
189 },
190 ),
191 (
192 Epoch(43),
193 AggregatorEpochSettings {
194 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
195 cardano_transactions_signing_config: Some(
196 CardanoTransactionsSigningConfig {
197 security_parameter: BlockNumber(2),
198 step: BlockNumber(20),
199 },
200 ),
201 },
202 ),
203 ])),
204 );
205
206 let configuration = local_provider.get_network_configuration(Epoch(43)).await.unwrap();
207
208 assert_eq!(Epoch(43), configuration.epoch);
209
210 assert_eq!(
211 MithrilNetworkConfigurationForEpoch {
212 protocol_parameters: ProtocolParameters::new(1000, 100, 0.1),
213 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
214 signed_entity_types_config: SignedEntityTypeConfiguration {
215 cardano_transactions: Some(CardanoTransactionsSigningConfig {
216 security_parameter: BlockNumber(1),
217 step: BlockNumber(10),
218 }),
219 },
220 },
221 configuration.configuration_for_aggregation
222 );
223
224 assert_eq!(
225 MithrilNetworkConfigurationForEpoch {
226 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
227 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
228 signed_entity_types_config: SignedEntityTypeConfiguration {
229 cardano_transactions: Some(CardanoTransactionsSigningConfig {
230 security_parameter: BlockNumber(2),
231 step: BlockNumber(20),
232 }),
233 },
234 },
235 configuration.configuration_for_next_aggregation
236 );
237
238 assert_eq!(
239 MithrilNetworkConfigurationForEpoch {
240 protocol_parameters: ProtocolParameters::new(3000, 300, 0.3),
241 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
242 signed_entity_types_config: SignedEntityTypeConfiguration {
243 cardano_transactions: Some(CardanoTransactionsSigningConfig {
244 security_parameter: BlockNumber(3),
245 step: BlockNumber(30),
246 }),
247 },
248 },
249 configuration.configuration_for_registration
250 );
251 }
252}