mithril_client/cardano_database_client/
api.rs1#[cfg(feature = "fs")]
2use std::path::Path;
3use std::sync::Arc;
4
5#[cfg(feature = "fs")]
6use slog::Logger;
7
8#[cfg(feature = "fs")]
9use mithril_common::{
10 crypto_helper::MKProof,
11 messages::{CardanoDatabaseSnapshotMessage, CertificateMessage},
12};
13
14use crate::aggregator_client::AggregatorClient;
15#[cfg(feature = "fs")]
16use crate::feedback::FeedbackSender;
17#[cfg(feature = "fs")]
18use crate::file_downloader::FileDownloader;
19#[cfg(feature = "fs")]
20use crate::utils::AncillaryVerifier;
21use crate::{CardanoDatabaseSnapshot, CardanoDatabaseSnapshotListItem, MithrilResult};
22
23use super::fetch::InternalArtifactRetriever;
24use super::statistics::InternalStatisticsSender;
25#[cfg(feature = "fs")]
26use super::{
27 download_unpack::InternalArtifactDownloader, proving::InternalArtifactProver,
28 DownloadUnpackOptions, ImmutableFileRange,
29};
30
31pub struct CardanoDatabaseClient {
33 pub(super) artifact_retriever: InternalArtifactRetriever,
34 #[cfg(feature = "fs")]
35 pub(super) artifact_downloader: InternalArtifactDownloader,
36 #[cfg(feature = "fs")]
37 pub(super) artifact_prover: InternalArtifactProver,
38 pub(super) statistics_sender: InternalStatisticsSender,
39}
40
41impl CardanoDatabaseClient {
42 pub fn new(
44 aggregator_client: Arc<dyn AggregatorClient>,
45 #[cfg(feature = "fs")] http_file_downloader: Arc<dyn FileDownloader>,
46 #[cfg(feature = "fs")] ancillary_verifier: Option<Arc<AncillaryVerifier>>,
47 #[cfg(feature = "fs")] feedback_sender: FeedbackSender,
48 #[cfg(feature = "fs")] logger: Logger,
49 ) -> Self {
50 #[cfg(feature = "fs")]
51 let logger =
52 mithril_common::logging::LoggerExtensions::new_with_component_name::<Self>(&logger);
53 Self {
54 artifact_retriever: InternalArtifactRetriever::new(aggregator_client.clone()),
55 #[cfg(feature = "fs")]
56 artifact_downloader: InternalArtifactDownloader::new(
57 http_file_downloader.clone(),
58 ancillary_verifier,
59 feedback_sender.clone(),
60 logger.clone(),
61 ),
62 #[cfg(feature = "fs")]
63 artifact_prover: InternalArtifactProver::new(
64 http_file_downloader.clone(),
65 logger.clone(),
66 ),
67 statistics_sender: InternalStatisticsSender::new(aggregator_client.clone()),
68 }
69 }
70
71 pub async fn list(&self) -> MithrilResult<Vec<CardanoDatabaseSnapshotListItem>> {
73 self.artifact_retriever.list().await
74 }
75
76 pub async fn get(&self, hash: &str) -> MithrilResult<Option<CardanoDatabaseSnapshot>> {
78 self.artifact_retriever.get(hash).await
79 }
80
81 #[cfg(feature = "fs")]
83 pub async fn download_unpack(
84 &self,
85 cardano_database_snapshot: &CardanoDatabaseSnapshotMessage,
86 immutable_file_range: &ImmutableFileRange,
87 target_dir: &Path,
88 download_unpack_options: DownloadUnpackOptions,
89 ) -> MithrilResult<()> {
90 self.artifact_downloader
91 .download_unpack(
92 cardano_database_snapshot,
93 immutable_file_range,
94 target_dir,
95 download_unpack_options,
96 )
97 .await
98 }
99
100 #[cfg(feature = "fs")]
102 pub async fn compute_merkle_proof(
103 &self,
104 certificate: &CertificateMessage,
105 cardano_database_snapshot: &CardanoDatabaseSnapshotMessage,
106 immutable_file_range: &ImmutableFileRange,
107 database_dir: &Path,
108 ) -> MithrilResult<MKProof> {
109 self.artifact_prover
110 .compute_merkle_proof(
111 certificate,
112 cardano_database_snapshot,
113 immutable_file_range,
114 database_dir,
115 )
116 .await
117 }
118
119 pub async fn add_statistics(
121 &self,
122 full_restoration: bool,
123 include_ancillary: bool,
124 number_of_immutable_files_restored: u64,
125 ) -> MithrilResult<()> {
126 self.statistics_sender
127 .add_statistics(
128 full_restoration,
129 include_ancillary,
130 number_of_immutable_files_restored,
131 )
132 .await
133 }
134}
135
136#[cfg(test)]
137pub(crate) mod test_dependency_injector {
138 use super::*;
139
140 #[cfg(feature = "fs")]
141 use mithril_common::crypto_helper::ManifestVerifierVerificationKey;
142
143 use crate::aggregator_client::MockAggregatorClient;
144 #[cfg(feature = "fs")]
145 use crate::file_downloader::{FileDownloader, MockFileDownloaderBuilder};
146 #[cfg(feature = "fs")]
147 use crate::{feedback::FeedbackReceiver, test_utils::TestLogger};
148
149 pub(crate) struct CardanoDatabaseClientDependencyInjector {
151 aggregator_client: MockAggregatorClient,
152 #[cfg(feature = "fs")]
153 http_file_downloader: Arc<dyn FileDownloader>,
154 #[cfg(feature = "fs")]
155 ancillary_verifier: Option<Arc<AncillaryVerifier>>,
156 #[cfg(feature = "fs")]
157 feedback_receivers: Vec<Arc<dyn FeedbackReceiver>>,
158 }
159
160 impl CardanoDatabaseClientDependencyInjector {
161 pub(crate) fn new() -> Self {
162 Self {
163 aggregator_client: MockAggregatorClient::new(),
164 #[cfg(feature = "fs")]
165 http_file_downloader: Arc::new(
166 MockFileDownloaderBuilder::default()
167 .with_compression(None)
168 .with_success()
169 .with_times(0)
170 .build(),
171 ),
172 #[cfg(feature = "fs")]
173 ancillary_verifier: None,
174 #[cfg(feature = "fs")]
175 feedback_receivers: vec![],
176 }
177 }
178
179 pub(crate) fn with_aggregator_client_mock_config<F>(mut self, config: F) -> Self
180 where
181 F: FnOnce(&mut MockAggregatorClient),
182 {
183 config(&mut self.aggregator_client);
184
185 self
186 }
187
188 #[cfg(feature = "fs")]
189 pub(crate) fn with_http_file_downloader(
190 self,
191 http_file_downloader: Arc<dyn FileDownloader>,
192 ) -> Self {
193 Self {
194 http_file_downloader,
195 ..self
196 }
197 }
198
199 #[cfg(feature = "fs")]
200 pub(crate) fn with_ancillary_verifier<T>(self, ancillary_verification_key: T) -> Self
201 where
202 T: TryInto<ManifestVerifierVerificationKey>,
203 T::Error: std::fmt::Debug,
204 {
205 Self {
206 ancillary_verifier: Some(Arc::new(AncillaryVerifier::new(
207 ancillary_verification_key.try_into().unwrap(),
208 ))),
209 ..self
210 }
211 }
212
213 #[cfg(feature = "fs")]
214 pub(crate) fn with_feedback_receivers(
215 self,
216 feedback_receivers: &[Arc<dyn FeedbackReceiver>],
217 ) -> Self {
218 Self {
219 feedback_receivers: feedback_receivers.to_vec(),
220 ..self
221 }
222 }
223
224 #[cfg(feature = "fs")]
225 pub(crate) fn build_cardano_database_client(self) -> CardanoDatabaseClient {
226 CardanoDatabaseClient::new(
227 Arc::new(self.aggregator_client),
228 self.http_file_downloader,
229 self.ancillary_verifier,
230 FeedbackSender::new(&self.feedback_receivers),
231 TestLogger::stdout(),
232 )
233 }
234
235 #[cfg(not(feature = "fs"))]
236 pub(crate) fn build_cardano_database_client(self) -> CardanoDatabaseClient {
237 CardanoDatabaseClient::new(Arc::new(self.aggregator_client))
238 }
239 }
240
241 mod tests {
242 use mockall::predicate;
243
244 use crate::aggregator_client::AggregatorRequest;
245 #[cfg(feature = "fs")]
246 use crate::feedback::StackFeedbackReceiver;
247
248 use super::*;
249
250 #[cfg(feature = "fs")]
251 #[test]
252 fn test_cardano_database_client_dependency_injector_builds() {
253 let _ = CardanoDatabaseClientDependencyInjector::new()
254 .with_aggregator_client_mock_config(|http_client| {
255 let message = vec![CardanoDatabaseSnapshotListItem {
256 hash: "hash-123".to_string(),
257 ..CardanoDatabaseSnapshotListItem::dummy()
258 }];
259 http_client
260 .expect_get_content()
261 .with(predicate::eq(
262 AggregatorRequest::ListCardanoDatabaseSnapshots,
263 ))
264 .return_once(move |_| Ok(serde_json::to_string(&message).unwrap()));
265 })
266 .with_http_file_downloader(Arc::new(
267 MockFileDownloaderBuilder::default()
268 .with_success()
269 .with_times(0)
270 .build(),
271 ))
272 .with_feedback_receivers(&[Arc::new(StackFeedbackReceiver::new())])
273 .build_cardano_database_client();
274 }
275
276 #[cfg(not(feature = "fs"))]
277 #[test]
278 fn test_cardano_database_client_dependency_injector_builds() {
279 let _ = CardanoDatabaseClientDependencyInjector::new()
280 .with_aggregator_client_mock_config(|http_client| {
281 let message = vec![CardanoDatabaseSnapshotListItem {
282 hash: "hash-123".to_string(),
283 ..CardanoDatabaseSnapshotListItem::dummy()
284 }];
285 http_client
286 .expect_get_content()
287 .with(predicate::eq(
288 AggregatorRequest::ListCardanoDatabaseSnapshots,
289 ))
290 .return_once(move |_| Ok(serde_json::to_string(&message).unwrap()));
291 })
292 .build_cardano_database_client();
293 }
294 }
295}