Skip to main content

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_digests_for_range]
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_digests_for_range]
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_digests_for_range(
60        &self,
61        dirpath: &Path,
62        range: &RangeInclusive<ImmutableFileNumber>,
63    ) -> Result<ComputedImmutablesDigests, ImmutableDigesterError> {
64        if self.is_success {
65            let immutable_file_paths = range
66                .clone()
67                .flat_map(|immutable_file_number| {
68                    vec![
69                        Path::new(&format!("{immutable_file_number:0>5}.chunk")).to_path_buf(),
70                        Path::new(&format!("{immutable_file_number:0>5}.primary")).to_path_buf(),
71                        Path::new(&format!("{immutable_file_number:0>5}.secondary")).to_path_buf(),
72                    ]
73                })
74                .collect::<Vec<_>>();
75            let digest = self.digest.read().await.clone();
76
77            Ok(ComputedImmutablesDigests::compute_immutables_digests(
78                BTreeMap::from_iter(immutable_file_paths.into_iter().map(|immutable_file_path| {
79                    (
80                        ImmutableFile::new(immutable_file_path).unwrap(),
81                        Some(digest.clone()),
82                    )
83                })),
84                slog::Logger::root(slog::Discard, slog::o!()),
85            )?)
86        } else {
87            Err(ImmutableDigesterError::NotEnoughImmutable {
88                expected_number: *range.end(),
89                found_number: None,
90                db_dir: dirpath.to_owned(),
91            })
92        }
93    }
94
95    async fn compute_merkle_tree(
96        &self,
97        dirpath: &Path,
98        beacon: &CardanoDbBeacon,
99    ) -> Result<MKTree<MKTreeStoreInMemory>, ImmutableDigesterError> {
100        if self.is_success {
101            let leaves = self.mktree_leaves.read().await;
102            Ok(MKTree::new(&leaves).unwrap())
103        } else {
104            Err(ImmutableDigesterError::NotEnoughImmutable {
105                expected_number: beacon.immutable_file_number,
106                found_number: None,
107                db_dir: dirpath.to_owned(),
108            })
109        }
110    }
111}