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    entities::{Epoch, SignerWithStake, StakeDistribution},
8    signable_builder::SignableBuilderService,
9    test::builder::MithrilFixture,
10};
11
12use mithril_era::{EraChecker, EraReader};
13use mithril_persistence::store::StakeStorer;
14use mithril_signed_entity_lock::SignedEntityTypeLock;
15use mithril_ticker::TickerService;
16
17use crate::{
18    EpochSettingsStorer, MetricsService, SignerRegisterer, SignerRegistrationRoundOpener,
19    SingleSignatureAuthenticator, VerificationKeyStorer,
20    database::repository::{
21        CertificateRepository, SignedEntityStorer, SignerGetter, StakePoolStore,
22    },
23    event_store::{EventMessage, TransmitterService},
24    services::{
25        CertificateChainSynchronizer, CertifierService, EpochService, LegacyProverService,
26        MessageService, ProverService, SignedEntityService, SignerRecorder, SignerSynchronizer,
27        StakeDistributionService, UpkeepService,
28    },
29};
30
31/// EpochServiceWrapper wraps
32pub type EpochServiceWrapper = Arc<RwLock<dyn EpochService>>;
33
34/// Dependencies container for the serve command
35pub struct ServeCommandDependenciesContainer {
36    /// Application root logger
37    pub(crate) root_logger: Logger,
38
39    /// Stake Store used by the StakeDistributionService
40    /// It shall be a private dependency.
41    pub(crate) stake_store: Arc<StakePoolStore>,
42
43    /// It shall be a private dependency.
44    /// Certificate store.
45    pub certificate_repository: Arc<CertificateRepository>,
46
47    /// Verification key store.
48    pub verification_key_store: Arc<dyn VerificationKeyStorer>,
49
50    /// Epoch settings storer.
51    pub epoch_settings_storer: Arc<dyn EpochSettingsStorer>,
52
53    /// Certificate chain synchronizer service
54    pub(crate) certificate_chain_synchronizer: Arc<dyn CertificateChainSynchronizer>,
55
56    /// Signer registerer service
57    pub signer_registerer: Arc<dyn SignerRegisterer>,
58
59    /// Signer synchronizer service
60    pub(crate) signer_synchronizer: Arc<dyn SignerSynchronizer>,
61
62    /// Signer registration round opener service
63    pub(crate) signer_registration_round_opener: Arc<dyn SignerRegistrationRoundOpener>,
64
65    /// Era checker service
66    pub(crate) era_checker: Arc<EraChecker>,
67
68    /// Era reader service
69    pub(crate) era_reader: Arc<EraReader>,
70
71    /// Event Transmitter Service
72    pub(crate) event_transmitter: Arc<TransmitterService<EventMessage>>,
73
74    /// API Version provider
75    pub(crate) api_version_provider: Arc<APIVersionProvider>,
76
77    /// Stake Distribution Service
78    pub(crate) stake_distribution_service: Arc<dyn StakeDistributionService>,
79
80    /// Signer Recorder
81    pub(crate) signer_recorder: Arc<dyn SignerRecorder>,
82
83    /// Signable Builder Service
84    pub signable_builder_service: Arc<dyn SignableBuilderService>,
85
86    /// Signed Entity Service
87    pub(crate) signed_entity_service: Arc<dyn SignedEntityService>,
88
89    /// Certifier Service
90    pub certifier_service: Arc<dyn CertifierService>,
91
92    /// Epoch service
93    pub(crate) epoch_service: EpochServiceWrapper,
94
95    /// Ticker Service
96    pub(crate) ticker_service: Arc<dyn TickerService>,
97
98    /// Signed Entity storer
99    pub signed_entity_storer: Arc<dyn SignedEntityStorer>,
100
101    /// Signer getter service
102    pub(crate) signer_getter: Arc<dyn SignerGetter>,
103
104    /// HTTP message service
105    pub message_service: Arc<dyn MessageService>,
106
107    /// Prover service
108    pub legacy_prover_service: Arc<dyn LegacyProverService>,
109
110    /// Legacy Prover service
111    pub prover_service: Arc<dyn ProverService>,
112
113    /// Signed Entity Type Lock
114    pub signed_entity_type_lock: Arc<SignedEntityTypeLock>,
115
116    /// Upkeep service
117    pub(crate) upkeep_service: Arc<dyn UpkeepService>,
118
119    /// Single signer authenticator
120    pub(crate) single_signer_authenticator: Arc<SingleSignatureAuthenticator>,
121
122    /// Metrics service
123    pub(crate) metrics_service: Arc<MetricsService>,
124}
125
126#[doc(hidden)]
127impl ServeCommandDependenciesContainer {
128    /// `TEST METHOD ONLY`
129    ///
130    /// Fill the stores of this container in a way to simulate an aggregator state
131    /// using the data from a precomputed fixture.
132    ///
133    /// Data will be inserted in the given `next_aggregation_epoch`, the current aggregation epoch
134    /// (`next_aggregation_epoch - 1`), and the signer registration epoch (`next_aggregation_epoch + 1`).
135    ///
136    /// Note: `epoch_settings` store must have data for the inserted epochs, this should be done
137    /// automatically when building the [ServeCommandDependenciesContainer] by `handle_discrepancies_at_startup`
138    pub async fn init_state_from_fixture(
139        &self,
140        fixture: &MithrilFixture,
141        next_aggregation_epoch: Epoch,
142    ) {
143        self.init_state_from_fixture_internal(
144            fixture,
145            [
146                next_aggregation_epoch.offset_to_signer_retrieval_epoch().unwrap(),
147                next_aggregation_epoch,
148                next_aggregation_epoch.offset_to_recording_epoch(),
149            ],
150        )
151        .await
152    }
153
154    /// `TEST METHOD ONLY`
155    ///
156    /// Fill the stores of this container in a way to simulate an aggregator state ready to sign a
157    /// genesis certificate using the data from a precomputed fixture.
158    ///
159    /// Data will be inserted in the given `next_aggregation_epoch`, the current aggregation epoch
160    /// (`next_aggregation_epoch - 1`).
161    ///
162    /// Note: `epoch_settings` store must have data for the inserted epochs, this should be done
163    /// automatically when building the [ServeCommandDependenciesContainer] by `handle_discrepancies_at_startup`
164    pub async fn init_state_from_fixture_for_genesis(
165        &self,
166        fixture: &MithrilFixture,
167        next_aggregation_epoch: Epoch,
168    ) {
169        self.init_state_from_fixture_internal(
170            fixture,
171            [
172                next_aggregation_epoch.offset_to_signer_retrieval_epoch().unwrap(),
173                next_aggregation_epoch,
174            ],
175        )
176        .await
177    }
178
179    async fn init_state_from_fixture_internal<const N: usize>(
180        &self,
181        fixture: &MithrilFixture,
182        epochs_to_fill: [Epoch; N],
183    ) {
184        for epoch in epochs_to_fill {
185            self.fill_verification_key_store(epoch, &fixture.signers_with_stake())
186                .await;
187            self.fill_stakes_store(epoch, fixture.signers_with_stake()).await;
188        }
189    }
190
191    async fn fill_verification_key_store(&self, target_epoch: Epoch, signers: &[SignerWithStake]) {
192        for signer in signers {
193            self.signer_recorder
194                .record_signer_registration(signer.party_id.clone())
195                .await
196                .expect("record_signer_registration should not fail");
197            self.verification_key_store
198                .save_verification_key(target_epoch, signer.clone())
199                .await
200                .expect("save_verification_key should not fail");
201        }
202    }
203
204    async fn fill_stakes_store(&self, target_epoch: Epoch, signers: Vec<SignerWithStake>) {
205        let _ = self
206            .stake_store
207            .save_stakes(
208                target_epoch,
209                signers.iter().map(|s| s.into()).collect::<StakeDistribution>(),
210            )
211            .await
212            .expect("save_stakes should not fail");
213    }
214}
215
216#[cfg(test)]
217pub(crate) mod tests {
218    use std::path::PathBuf;
219
220    use crate::{ServeCommandConfiguration, dependency_injection::DependenciesBuilder};
221
222    use super::*;
223
224    /// Initialize dependency container with a unique temporary snapshot directory build from test path.
225    /// This macro should used directly in a function test to be able to retrieve the function name.
226    #[macro_export]
227    macro_rules! initialize_dependencies {
228        () => {{ initialize_dependencies(mithril_common::temp_dir!()) }};
229    }
230
231    pub async fn initialize_dependencies(tmp_path: PathBuf) -> ServeCommandDependenciesContainer {
232        let config = ServeCommandConfiguration::new_sample(tmp_path);
233
234        let mut builder = DependenciesBuilder::new_with_stdout_logger(Arc::new(config));
235
236        builder.build_serve_dependencies_container().await.unwrap()
237    }
238}