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: Some(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: 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: CardanoTransactionsSigningConfig {
184 security_parameter: BlockNumber(1),
185 step: BlockNumber(10),
186 },
187 },
188 ),
189 (
190 Epoch(43),
191 AggregatorEpochSettings {
192 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
193 cardano_transactions_signing_config: CardanoTransactionsSigningConfig {
194 security_parameter: BlockNumber(2),
195 step: BlockNumber(20),
196 },
197 },
198 ),
199 ])),
200 );
201
202 let configuration = local_provider.get_network_configuration(Epoch(43)).await.unwrap();
203
204 assert_eq!(Epoch(43), configuration.epoch);
205
206 assert_eq!(
207 MithrilNetworkConfigurationForEpoch {
208 protocol_parameters: ProtocolParameters::new(1000, 100, 0.1),
209 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
210 signed_entity_types_config: SignedEntityTypeConfiguration {
211 cardano_transactions: Some(CardanoTransactionsSigningConfig {
212 security_parameter: BlockNumber(1),
213 step: BlockNumber(10),
214 }),
215 },
216 },
217 configuration.configuration_for_aggregation
218 );
219
220 assert_eq!(
221 MithrilNetworkConfigurationForEpoch {
222 protocol_parameters: ProtocolParameters::new(2000, 200, 0.2),
223 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
224 signed_entity_types_config: SignedEntityTypeConfiguration {
225 cardano_transactions: Some(CardanoTransactionsSigningConfig {
226 security_parameter: BlockNumber(2),
227 step: BlockNumber(20),
228 }),
229 },
230 },
231 configuration.configuration_for_next_aggregation
232 );
233
234 assert_eq!(
235 MithrilNetworkConfigurationForEpoch {
236 protocol_parameters: ProtocolParameters::new(3000, 300, 0.3),
237 enabled_signed_entity_types: SignedEntityTypeDiscriminants::all(),
238 signed_entity_types_config: SignedEntityTypeConfiguration {
239 cardano_transactions: Some(CardanoTransactionsSigningConfig {
240 security_parameter: BlockNumber(3),
241 step: BlockNumber(30),
242 }),
243 },
244 },
245 configuration.configuration_for_registration
246 );
247 }
248}