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, MessageService,
26        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 prover_service: Arc<dyn ProverService>,
109
110    /// Signed Entity Type Lock
111    pub signed_entity_type_lock: Arc<SignedEntityTypeLock>,
112
113    /// Upkeep service
114    pub(crate) upkeep_service: Arc<dyn UpkeepService>,
115
116    /// Single signer authenticator
117    pub(crate) single_signer_authenticator: Arc<SingleSignatureAuthenticator>,
118
119    /// Metrics service
120    pub(crate) metrics_service: Arc<MetricsService>,
121}
122
123#[doc(hidden)]
124impl ServeCommandDependenciesContainer {
125    /// `TEST METHOD ONLY`
126    ///
127    /// Fill the stores of this container in a way to simulate an aggregator state
128    /// using the data from a precomputed fixture.
129    ///
130    /// Data will be inserted in the given `next_aggregation_epoch`, the current aggregation epoch
131    /// (`next_aggregation_epoch - 1`), and the signer registration epoch (`next_aggregation_epoch + 1`).
132    ///
133    /// Note: `epoch_settings` store must have data for the inserted epochs, this should be done
134    /// automatically when building the [ServeCommandDependenciesContainer] by `handle_discrepancies_at_startup`
135    pub async fn init_state_from_fixture(
136        &self,
137        fixture: &MithrilFixture,
138        next_aggregation_epoch: Epoch,
139    ) {
140        self.init_state_from_fixture_internal(
141            fixture,
142            [
143                next_aggregation_epoch.offset_to_signer_retrieval_epoch().unwrap(),
144                next_aggregation_epoch,
145                next_aggregation_epoch.offset_to_recording_epoch(),
146            ],
147        )
148        .await
149    }
150
151    /// `TEST METHOD ONLY`
152    ///
153    /// Fill the stores of this container in a way to simulate an aggregator state ready to sign a
154    /// genesis certificate using the data from a precomputed fixture.
155    ///
156    /// Data will be inserted in the given `next_aggregation_epoch`, the current aggregation epoch
157    /// (`next_aggregation_epoch - 1`).
158    ///
159    /// Note: `epoch_settings` store must have data for the inserted epochs, this should be done
160    /// automatically when building the [ServeCommandDependenciesContainer] by `handle_discrepancies_at_startup`
161    pub async fn init_state_from_fixture_for_genesis(
162        &self,
163        fixture: &MithrilFixture,
164        next_aggregation_epoch: Epoch,
165    ) {
166        self.init_state_from_fixture_internal(
167            fixture,
168            [
169                next_aggregation_epoch.offset_to_signer_retrieval_epoch().unwrap(),
170                next_aggregation_epoch,
171            ],
172        )
173        .await
174    }
175
176    async fn init_state_from_fixture_internal<const N: usize>(
177        &self,
178        fixture: &MithrilFixture,
179        epochs_to_fill: [Epoch; N],
180    ) {
181        for epoch in epochs_to_fill {
182            self.fill_verification_key_store(epoch, &fixture.signers_with_stake())
183                .await;
184            self.fill_stakes_store(epoch, fixture.signers_with_stake()).await;
185        }
186    }
187
188    async fn fill_verification_key_store(&self, target_epoch: Epoch, signers: &[SignerWithStake]) {
189        for signer in signers {
190            self.signer_recorder
191                .record_signer_registration(signer.party_id.clone())
192                .await
193                .expect("record_signer_registration should not fail");
194            self.verification_key_store
195                .save_verification_key(target_epoch, signer.clone())
196                .await
197                .expect("save_verification_key should not fail");
198        }
199    }
200
201    async fn fill_stakes_store(&self, target_epoch: Epoch, signers: Vec<SignerWithStake>) {
202        let _ = self
203            .stake_store
204            .save_stakes(
205                target_epoch,
206                signers.iter().map(|s| s.into()).collect::<StakeDistribution>(),
207            )
208            .await
209            .expect("save_stakes should not fail");
210    }
211}
212
213#[cfg(test)]
214pub(crate) mod tests {
215    use std::path::PathBuf;
216
217    use crate::{ServeCommandConfiguration, dependency_injection::DependenciesBuilder};
218
219    use super::*;
220
221    /// Initialize dependency container with a unique temporary snapshot directory build from test path.
222    /// This macro should used directly in a function test to be able to retrieve the function name.
223    #[macro_export]
224    macro_rules! initialize_dependencies {
225        () => {{ initialize_dependencies(mithril_common::temp_dir!()) }};
226    }
227
228    pub async fn initialize_dependencies(tmp_path: PathBuf) -> ServeCommandDependenciesContainer {
229        let config = ServeCommandConfiguration::new_sample(tmp_path);
230
231        let mut builder = DependenciesBuilder::new_with_stdout_logger(Arc::new(config));
232
233        builder.build_serve_dependencies_container().await.unwrap()
234    }
235}