mithril_aggregator/dependency_injection/
containers.rs

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