mithril_cardano_node_internal_database/test/double/
immutable_digester.rs

1use std::{collections::BTreeMap, ops::RangeInclusive, path::Path};
2
3use async_trait::async_trait;
4use tokio::sync::RwLock;
5
6use mithril_common::{
7    crypto_helper::{MKTree, MKTreeStoreInMemory},
8    entities::{CardanoDbBeacon, ImmutableFileNumber},
9};
10
11use crate::digesters::{ComputedImmutablesDigests, ImmutableDigester, ImmutableDigesterError};
12use crate::entities::ImmutableFile;
13
14/// A [ImmutableDigester] returning configurable result for testing purpose.
15pub struct DumbImmutableDigester {
16    digest: RwLock<String>,
17    mktree_leaves: RwLock<Vec<String>>,
18    is_success: bool,
19}
20
21impl DumbImmutableDigester {
22    /// Set the digest returned by [compute_digest][DumbImmutableDigester::compute_digest]
23    pub fn with_digest(mut self, new_digest: &str) -> Self {
24        self.digest = RwLock::new(new_digest.to_string());
25        self
26    }
27
28    /// Set the leaves used to construct the merkle tree returned by [compute_merkle_tree][DumbImmutableDigester::compute_merkle_tree]
29    pub fn with_merkle_tree(mut self, leaves: Vec<String>) -> Self {
30        self.mktree_leaves = RwLock::new(leaves);
31        self
32    }
33
34    /// Update digest returned by [compute_digest][DumbImmutableDigester::compute_digest]
35    pub async fn update_digest(&self, new_digest: String) {
36        let mut digest = self.digest.write().await;
37        *digest = new_digest;
38    }
39
40    /// Update the leaves used to construct the merkle tree returned by [compute_merkle_tree][DumbImmutableDigester::compute_merkle_tree]
41    pub async fn update_merkle_tree(&self, leaves: Vec<String>) {
42        let mut mktree_leaves = self.mktree_leaves.write().await;
43        *mktree_leaves = leaves;
44    }
45}
46
47impl Default for DumbImmutableDigester {
48    fn default() -> Self {
49        Self {
50            digest: RwLock::new(String::from("1234")),
51            mktree_leaves: RwLock::new(vec!["1".to_string(), "2".to_string(), "3".to_string()]),
52            is_success: true,
53        }
54    }
55}
56
57#[async_trait]
58impl ImmutableDigester for DumbImmutableDigester {
59    async fn compute_digest(
60        &self,
61        dirpath: &Path,
62        beacon: &CardanoDbBeacon,
63    ) -> Result<String, ImmutableDigesterError> {
64        if self.is_success {
65            Ok(self.digest.read().await.clone())
66        } else {
67            Err(ImmutableDigesterError::NotEnoughImmutable {
68                expected_number: beacon.immutable_file_number,
69                found_number: None,
70                db_dir: dirpath.to_owned(),
71            })
72        }
73    }
74
75    async fn compute_digests_for_range(
76        &self,
77        dirpath: &Path,
78        range: &RangeInclusive<ImmutableFileNumber>,
79    ) -> Result<ComputedImmutablesDigests, ImmutableDigesterError> {
80        if self.is_success {
81            let immutable_file_paths = range
82                .clone()
83                .flat_map(|immutable_file_number| {
84                    vec![
85                        Path::new(&format!("{immutable_file_number:0>5}.chunk")).to_path_buf(),
86                        Path::new(&format!("{immutable_file_number:0>5}.primary")).to_path_buf(),
87                        Path::new(&format!("{immutable_file_number:0>5}.secondary")).to_path_buf(),
88                    ]
89                })
90                .collect::<Vec<_>>();
91            let digest = self.digest.read().await.clone();
92
93            Ok(ComputedImmutablesDigests::compute_immutables_digests(
94                BTreeMap::from_iter(immutable_file_paths.into_iter().map(|immutable_file_path| {
95                    (
96                        ImmutableFile::new(immutable_file_path).unwrap(),
97                        Some(digest.clone()),
98                    )
99                })),
100                slog::Logger::root(slog::Discard, slog::o!()),
101            )?)
102        } else {
103            Err(ImmutableDigesterError::NotEnoughImmutable {
104                expected_number: *range.end(),
105                found_number: None,
106                db_dir: dirpath.to_owned(),
107            })
108        }
109    }
110
111    async fn compute_merkle_tree(
112        &self,
113        dirpath: &Path,
114        beacon: &CardanoDbBeacon,
115    ) -> Result<MKTree<MKTreeStoreInMemory>, ImmutableDigesterError> {
116        if self.is_success {
117            let leaves = self.mktree_leaves.read().await;
118            Ok(MKTree::new(&leaves).unwrap())
119        } else {
120            Err(ImmutableDigesterError::NotEnoughImmutable {
121                expected_number: beacon.immutable_file_number,
122                found_number: None,
123                db_dir: dirpath.to_owned(),
124            })
125        }
126    }
127}