mithril_aggregator/dependency_injection/containers/
serve.rs

1use slog::Logger;
2use std::sync::Arc;
3use tokio::sync::RwLock;
4
5use mithril_common::{
6    api_version::APIVersionProvider,
7    chain_observer::ChainObserver,
8    entities::{
9        CardanoTransactionsSigningConfig, Epoch, ProtocolParameters, SignerWithStake,
10        StakeDistribution,
11    },
12    era::{EraChecker, EraReader},
13    signable_builder::SignableBuilderService,
14    test_utils::MithrilFixture,
15    TickerService,
16};
17
18use mithril_persistence::store::StakeStorer;
19use mithril_signed_entity_lock::SignedEntityTypeLock;
20
21use crate::{
22    database::repository::{
23        CertificateRepository, SignedEntityStorer, SignerGetter, StakePoolStore,
24    },
25    entities::AggregatorEpochSettings,
26    event_store::{EventMessage, TransmitterService},
27    services::{
28        CertifierService, EpochService, MessageService, ProverService, SignedEntityService,
29        SignerRecorder, SignerSynchronizer, StakeDistributionService, UpkeepService,
30    },
31    EpochSettingsStorer, MetricsService, SignerRegisterer, SignerRegistrationRoundOpener,
32    SingleSignatureAuthenticator, VerificationKeyStorer,
33};
34
35/// EpochServiceWrapper wraps
36pub type EpochServiceWrapper = Arc<RwLock<dyn EpochService>>;
37
38/// Dependencies container for the serve command
39pub struct ServeCommandDependenciesContainer {
40    /// Application root logger
41    pub(crate) root_logger: Logger,
42
43    /// Stake Store used by the StakeDistributionService
44    /// It shall be a private dependency.
45    pub(crate) stake_store: Arc<StakePoolStore>,
46
47    /// It shall be a private dependency.
48    /// Certificate store.
49    pub certificate_repository: Arc<CertificateRepository>,
50
51    /// Verification key store.
52    pub verification_key_store: Arc<dyn VerificationKeyStorer>,
53
54    /// Epoch settings storer.
55    pub epoch_settings_storer: Arc<dyn EpochSettingsStorer>,
56
57    /// Chain observer service.
58    pub(crate) chain_observer: Arc<dyn ChainObserver>,
59
60    /// Signer registerer service
61    pub signer_registerer: Arc<dyn SignerRegisterer>,
62
63    /// Signer synchronizer service
64    pub(crate) signer_synchronizer: Arc<dyn SignerSynchronizer>,
65
66    /// Signer registration round opener service
67    pub(crate) signer_registration_round_opener: Arc<dyn SignerRegistrationRoundOpener>,
68
69    /// Era checker service
70    pub(crate) era_checker: Arc<EraChecker>,
71
72    /// Era reader service
73    pub(crate) era_reader: Arc<EraReader>,
74
75    /// Event Transmitter Service
76    pub(crate) event_transmitter: Arc<TransmitterService<EventMessage>>,
77
78    /// API Version provider
79    pub(crate) api_version_provider: Arc<APIVersionProvider>,
80
81    /// Stake Distribution Service
82    pub(crate) stake_distribution_service: Arc<dyn StakeDistributionService>,
83
84    /// Signer Recorder
85    pub(crate) signer_recorder: Arc<dyn SignerRecorder>,
86
87    /// Signable Builder Service
88    pub signable_builder_service: Arc<dyn SignableBuilderService>,
89
90    /// Signed Entity Service
91    pub(crate) signed_entity_service: Arc<dyn SignedEntityService>,
92
93    /// Certifier Service
94    pub certifier_service: Arc<dyn CertifierService>,
95
96    /// Epoch service
97    pub(crate) epoch_service: EpochServiceWrapper,
98
99    /// Ticker Service
100    pub(crate) ticker_service: Arc<dyn TickerService>,
101
102    /// Signed Entity storer
103    pub signed_entity_storer: Arc<dyn SignedEntityStorer>,
104
105    /// Signer getter service
106    pub(crate) signer_getter: Arc<dyn SignerGetter>,
107
108    /// HTTP message service
109    pub message_service: Arc<dyn MessageService>,
110
111    /// Prover service
112    pub prover_service: Arc<dyn ProverService>,
113
114    /// Signed Entity Type Lock
115    pub signed_entity_type_lock: Arc<SignedEntityTypeLock>,
116
117    /// Upkeep service
118    pub(crate) upkeep_service: Arc<dyn UpkeepService>,
119
120    /// Single signer authenticator
121    pub(crate) single_signer_authenticator: Arc<SingleSignatureAuthenticator>,
122
123    /// Metrics service
124    pub(crate) metrics_service: Arc<MetricsService>,
125}
126
127#[doc(hidden)]
128impl ServeCommandDependenciesContainer {
129    /// `TEST METHOD ONLY`
130    ///
131    /// Get the first two epochs that will be used by a newly started aggregator
132    pub async fn get_genesis_epochs(&self) -> (Epoch, Epoch) {
133        let current_epoch = self
134            .chain_observer
135            .get_current_epoch()
136            .await
137            .expect("get_current_epoch should not fail")
138            .expect("an epoch should've been set to the chain observer");
139        let work_epoch = current_epoch
140            .offset_to_signer_retrieval_epoch()
141            .expect("epoch.offset_by SIGNER_EPOCH_RETRIEVAL_OFFSET should not fail");
142        let epoch_to_sign = current_epoch.offset_to_next_signer_retrieval_epoch();
143
144        (work_epoch, epoch_to_sign)
145    }
146
147    /// `TEST METHOD ONLY`
148    ///
149    /// Fill the stores of a [DependencyManager] in a way to simulate an aggregator state
150    /// using the data from a precomputed fixture.
151    pub async fn init_state_from_fixture(
152        &self,
153        fixture: &MithrilFixture,
154        cardano_transactions_signing_config: &CardanoTransactionsSigningConfig,
155        target_epochs: &[Epoch],
156    ) {
157        for epoch in target_epochs {
158            self.epoch_settings_storer
159                .save_epoch_settings(
160                    *epoch,
161                    AggregatorEpochSettings {
162                        protocol_parameters: fixture.protocol_parameters(),
163                        cardano_transactions_signing_config: cardano_transactions_signing_config
164                            .clone(),
165                    },
166                )
167                .await
168                .expect("save_epoch_settings should not fail");
169            self.fill_verification_key_store(*epoch, &fixture.signers_with_stake())
170                .await;
171            self.fill_stakes_store(*epoch, fixture.signers_with_stake())
172                .await;
173        }
174    }
175
176    /// `TEST METHOD ONLY`
177    ///
178    /// Fill the stores of a [DependencyManager] in a way to simulate an aggregator genesis state.
179    ///
180    /// For the current and the next epoch:
181    /// * Fill the [VerificationKeyStorer] with the given signers keys.
182    /// * Fill the [StakeStore] with the given signers stakes.
183    /// * Fill the [ProtocolParametersStore] with the given parameters.
184    pub async fn prepare_for_genesis(
185        &self,
186        genesis_signers: Vec<SignerWithStake>,
187        second_epoch_signers: Vec<SignerWithStake>,
188        genesis_protocol_parameters: &ProtocolParameters,
189        cardano_transactions_signing_config: &CardanoTransactionsSigningConfig,
190    ) {
191        self.init_epoch_settings_storer(&AggregatorEpochSettings {
192            protocol_parameters: genesis_protocol_parameters.clone(),
193            cardano_transactions_signing_config: cardano_transactions_signing_config.clone(),
194        })
195        .await;
196
197        let (work_epoch, epoch_to_sign) = self.get_genesis_epochs().await;
198        for (epoch, signers) in [
199            (work_epoch, genesis_signers),
200            (epoch_to_sign, second_epoch_signers),
201        ] {
202            self.fill_verification_key_store(epoch, &signers).await;
203            self.fill_stakes_store(epoch, signers).await;
204        }
205    }
206
207    /// `TEST METHOD ONLY`
208    ///
209    /// Fill up to the first three epochs of the [EpochSettingsStorer] with the given value.
210    pub async fn init_epoch_settings_storer(&self, epoch_settings: &AggregatorEpochSettings) {
211        let (work_epoch, epoch_to_sign) = self.get_genesis_epochs().await;
212        let mut epochs_to_save = Vec::new();
213        epochs_to_save.push(work_epoch);
214        epochs_to_save.push(epoch_to_sign);
215        epochs_to_save.push(epoch_to_sign.next());
216        for epoch in epochs_to_save {
217            self.epoch_settings_storer
218                .save_epoch_settings(epoch, epoch_settings.clone())
219                .await
220                .expect("save_epoch_settings should not fail");
221        }
222    }
223
224    async fn fill_verification_key_store(&self, target_epoch: Epoch, signers: &[SignerWithStake]) {
225        for signer in signers {
226            self.signer_recorder
227                .record_signer_registration(signer.party_id.clone())
228                .await
229                .expect("record_signer_registration should not fail");
230            self.verification_key_store
231                .save_verification_key(target_epoch, signer.clone())
232                .await
233                .expect("save_verification_key should not fail");
234        }
235    }
236
237    async fn fill_stakes_store(&self, target_epoch: Epoch, signers: Vec<SignerWithStake>) {
238        let _ = self
239            .stake_store
240            .save_stakes(
241                target_epoch,
242                signers
243                    .iter()
244                    .map(|s| s.into())
245                    .collect::<StakeDistribution>(),
246            )
247            .await
248            .expect("save_stakes should not fail");
249    }
250}
251
252#[cfg(test)]
253pub(crate) mod tests {
254
255    use std::{path::PathBuf, sync::Arc};
256
257    use crate::{
258        dependency_injection::DependenciesBuilder, ServeCommandConfiguration,
259        ServeCommandDependenciesContainer,
260    };
261
262    /// Initialize dependency container with a unique temporary snapshot directory build from test path.
263    /// This macro should used directly in a function test to be able to retrieve the function name.
264    #[macro_export]
265    macro_rules! initialize_dependencies {
266        () => {{
267            initialize_dependencies(mithril_common::temp_dir!())
268        }};
269    }
270
271    pub async fn initialize_dependencies(tmp_path: PathBuf) -> ServeCommandDependenciesContainer {
272        let config = ServeCommandConfiguration::new_sample(tmp_path);
273
274        let mut builder = DependenciesBuilder::new_with_stdout_logger(Arc::new(config));
275
276        builder.build_serve_dependencies_container().await.unwrap()
277    }
278}