mithril_aggregator/dependency_injection/builder/enablers/
cardano_node.rs1use anyhow::Context;
2use std::sync::Arc;
3use tokio::sync::Mutex;
4
5use mithril_common::cardano_block_scanner::{BlockScanner, CardanoBlockScanner};
6use mithril_common::chain_observer::{
7 CardanoCliRunner, ChainObserver, ChainObserverBuilder, FakeObserver,
8};
9use mithril_common::chain_reader::{ChainBlockReader, PallasChainReader};
10use mithril_common::digesters::{CardanoImmutableDigester, ImmutableDigester};
11use mithril_common::entities::SignedEntityTypeDiscriminants;
12use mithril_signed_entity_preloader::{
13 CardanoTransactionsPreloader, CardanoTransactionsPreloaderActivation,
14};
15
16use crate::dependency_injection::{DependenciesBuilder, Result};
17use crate::services::{MithrilStakeDistributionService, StakeDistributionService};
18use crate::ExecutionEnvironment;
19
20impl DependenciesBuilder {
21 async fn build_chain_observer(&mut self) -> Result<Arc<dyn ChainObserver>> {
22 let chain_observer: Arc<dyn ChainObserver> = match self.configuration.environment {
23 ExecutionEnvironment::Production => {
24 let cardano_cli_runner = &self.get_cardano_cli_runner().await?;
25 let chain_observer_type = &self.configuration.chain_observer_type;
26 let cardano_node_socket_path = &self.configuration.cardano_node_socket_path;
27 let cardano_network = &self
28 .configuration
29 .get_network()
30 .with_context(|| "Dependencies Builder can not get Cardano network while building the chain observer")?;
31 let chain_observer_builder = ChainObserverBuilder::new(
32 chain_observer_type,
33 cardano_node_socket_path,
34 cardano_network,
35 Some(cardano_cli_runner),
36 );
37
38 chain_observer_builder
39 .build()
40 .with_context(|| "Dependencies Builder can not build chain observer")?
41 }
42 _ => Arc::new(FakeObserver::default()),
43 };
44
45 Ok(chain_observer)
46 }
47
48 pub async fn get_chain_observer(&mut self) -> Result<Arc<dyn ChainObserver>> {
50 if self.chain_observer.is_none() {
51 self.chain_observer = Some(self.build_chain_observer().await?);
52 }
53
54 Ok(self.chain_observer.as_ref().cloned().unwrap())
55 }
56
57 async fn build_cardano_cli_runner(&mut self) -> Result<Box<CardanoCliRunner>> {
58 let cli_runner = CardanoCliRunner::new(
59 self.configuration.cardano_cli_path.clone(),
60 self.configuration.cardano_node_socket_path.clone(),
61 self.configuration.get_network().with_context(|| {
62 "Dependencies Builder can not get Cardano network while building cardano cli runner"
63 })?,
64 );
65
66 Ok(Box::new(cli_runner))
67 }
68
69 pub async fn get_cardano_cli_runner(&mut self) -> Result<Box<CardanoCliRunner>> {
71 if self.cardano_cli_runner.is_none() {
72 self.cardano_cli_runner = Some(self.build_cardano_cli_runner().await?);
73 }
74
75 Ok(self.cardano_cli_runner.as_ref().cloned().unwrap())
76 }
77
78 async fn build_chain_block_reader(&mut self) -> Result<Arc<Mutex<dyn ChainBlockReader>>> {
79 let chain_block_reader = PallasChainReader::new(
80 &self.configuration.cardano_node_socket_path,
81 self.configuration.get_network()?,
82 self.root_logger(),
83 );
84
85 Ok(Arc::new(Mutex::new(chain_block_reader)))
86 }
87
88 pub async fn get_chain_block_reader(&mut self) -> Result<Arc<Mutex<dyn ChainBlockReader>>> {
90 if self.chain_block_reader.is_none() {
91 self.chain_block_reader = Some(self.build_chain_block_reader().await?);
92 }
93
94 Ok(self.chain_block_reader.as_ref().cloned().unwrap())
95 }
96
97 async fn build_block_scanner(&mut self) -> Result<Arc<dyn BlockScanner>> {
98 let block_scanner = CardanoBlockScanner::new(
99 self.get_chain_block_reader().await?,
100 self.configuration
101 .cardano_transactions_block_streamer_max_roll_forwards_per_poll,
102 self.root_logger(),
103 );
104
105 Ok(Arc::new(block_scanner))
106 }
107
108 pub async fn get_block_scanner(&mut self) -> Result<Arc<dyn BlockScanner>> {
110 if self.block_scanner.is_none() {
111 self.block_scanner = Some(self.build_block_scanner().await?);
112 }
113
114 Ok(self.block_scanner.as_ref().cloned().unwrap())
115 }
116
117 async fn build_immutable_digester(&mut self) -> Result<Arc<dyn ImmutableDigester>> {
118 let immutable_digester_cache = match self.configuration.environment {
119 ExecutionEnvironment::Production => Some(self.get_immutable_cache_provider().await?),
120 _ => None,
121 };
122 let digester = CardanoImmutableDigester::new(
123 self.configuration.get_network()?.to_string(),
124 immutable_digester_cache,
125 self.root_logger(),
126 );
127
128 Ok(Arc::new(digester))
129 }
130
131 pub async fn get_immutable_digester(&mut self) -> Result<Arc<dyn ImmutableDigester>> {
133 if self.immutable_digester.is_none() {
134 self.immutable_digester = Some(self.build_immutable_digester().await?);
135 }
136
137 Ok(self.immutable_digester.as_ref().cloned().unwrap())
138 }
139
140 pub async fn create_cardano_transactions_preloader(
142 &mut self,
143 ) -> Result<Arc<CardanoTransactionsPreloader>> {
144 let activation = self
145 .configuration
146 .compute_allowed_signed_entity_types_discriminants()?
147 .contains(&SignedEntityTypeDiscriminants::CardanoTransactions);
148 let cardano_transactions_preloader = CardanoTransactionsPreloader::new(
149 self.get_signed_entity_lock().await?,
150 self.get_transactions_importer().await?,
151 self.configuration
152 .cardano_transactions_signing_config
153 .security_parameter,
154 self.get_chain_observer().await?,
155 self.root_logger(),
156 Arc::new(CardanoTransactionsPreloaderActivation::new(activation)),
157 );
158
159 Ok(Arc::new(cardano_transactions_preloader))
160 }
161
162 async fn build_stake_distribution_service(
163 &mut self,
164 ) -> Result<Arc<dyn StakeDistributionService>> {
165 let stake_distribution_service = Arc::new(MithrilStakeDistributionService::new(
166 self.get_stake_store().await?,
167 self.get_chain_observer().await?,
168 ));
169
170 Ok(stake_distribution_service)
171 }
172
173 pub async fn get_stake_distribution_service(
175 &mut self,
176 ) -> Result<Arc<dyn StakeDistributionService>> {
177 if self.stake_distribution_service.is_none() {
178 self.stake_distribution_service = Some(self.build_stake_distribution_service().await?);
179 }
180
181 Ok(self.stake_distribution_service.as_ref().cloned().unwrap())
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use mithril_common::{entities::SignedEntityTypeDiscriminants, temp_dir};
188
189 use crate::Configuration;
190
191 use super::*;
192
193 #[tokio::test]
194 async fn cardano_transactions_preloader_activated_with_cardano_transactions_signed_entity_type_in_configuration(
195 ) {
196 assert_cardano_transactions_preloader_activation(
197 SignedEntityTypeDiscriminants::CardanoTransactions.to_string(),
198 true,
199 )
200 .await;
201 assert_cardano_transactions_preloader_activation(
202 SignedEntityTypeDiscriminants::MithrilStakeDistribution.to_string(),
203 false,
204 )
205 .await;
206 }
207
208 async fn assert_cardano_transactions_preloader_activation(
209 signed_entity_types: String,
210 expected_activation: bool,
211 ) {
212 let configuration = Configuration {
213 signed_entity_types: Some(signed_entity_types),
214 ..Configuration::new_sample(temp_dir!())
215 };
216 let mut dep_builder = DependenciesBuilder::new_with_stdout_logger(configuration);
217
218 let cardano_transactions_preloader = dep_builder
219 .create_cardano_transactions_preloader()
220 .await
221 .unwrap();
222
223 let is_activated = cardano_transactions_preloader.is_activated().await.unwrap();
224 assert_eq!(
225 expected_activation, is_activated,
226 "'is_activated' expected {}, but was {}",
227 expected_activation, is_activated
228 );
229 }
230}