mithril_common/digesters/
dumb_immutable_digester.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::{collections::BTreeMap, ops::RangeInclusive, path::Path};

use crate::{
    crypto_helper::{MKTree, MKTreeStoreInMemory},
    digesters::{ImmutableDigester, ImmutableDigesterError},
    entities::{CardanoDbBeacon, ImmutableFileNumber},
};
use async_trait::async_trait;
use tokio::sync::RwLock;

use super::{immutable_digester::ComputedImmutablesDigests, ImmutableFile};

/// A [ImmutableDigester] returning configurable result for testing purpose.
pub struct DumbImmutableDigester {
    digest: RwLock<String>,
    mktree_leaves: RwLock<Vec<String>>,
    is_success: bool,
}

impl DumbImmutableDigester {
    /// Set the digest returned by [compute_digest][DumbImmutableDigester::compute_digest]
    pub fn with_digest(mut self, new_digest: &str) -> Self {
        self.digest = RwLock::new(new_digest.to_string());
        self
    }

    /// Set the leaves used to construct the merkle tree returned by [compute_merkle_tree][DumbImmutableDigester::compute_merkle_tree]
    pub fn with_merkle_tree(mut self, leaves: Vec<String>) -> Self {
        self.mktree_leaves = RwLock::new(leaves);
        self
    }

    /// Update digest returned by [compute_digest][DumbImmutableDigester::compute_digest]
    pub async fn update_digest(&self, new_digest: String) {
        let mut digest = self.digest.write().await;
        *digest = new_digest;
    }

    /// Update the leaves used to construct the merkle tree returned by [compute_merkle_tree][DumbImmutableDigester::compute_merkle_tree]
    pub async fn update_merkle_tree(&self, leaves: Vec<String>) {
        let mut mktree_leaves = self.mktree_leaves.write().await;
        *mktree_leaves = leaves;
    }
}

impl Default for DumbImmutableDigester {
    fn default() -> Self {
        Self {
            digest: RwLock::new(String::from("1234")),
            mktree_leaves: RwLock::new(vec!["1".to_string(), "2".to_string(), "3".to_string()]),
            is_success: true,
        }
    }
}

#[async_trait]
impl ImmutableDigester for DumbImmutableDigester {
    async fn compute_digest(
        &self,
        dirpath: &Path,
        beacon: &CardanoDbBeacon,
    ) -> Result<String, ImmutableDigesterError> {
        if self.is_success {
            Ok(self.digest.read().await.clone())
        } else {
            Err(ImmutableDigesterError::NotEnoughImmutable {
                expected_number: beacon.immutable_file_number,
                found_number: None,
                db_dir: dirpath.to_owned(),
            })
        }
    }

    async fn compute_digests_for_range(
        &self,
        dirpath: &Path,
        range: &RangeInclusive<ImmutableFileNumber>,
    ) -> Result<ComputedImmutablesDigests, ImmutableDigesterError> {
        if self.is_success {
            let immutable_file_paths = range
                .clone()
                .flat_map(|immutable_file_number| {
                    vec![
                        Path::new(&format!("{immutable_file_number:0>5}.chunk")).to_path_buf(),
                        Path::new(&format!("{immutable_file_number:0>5}.primary")).to_path_buf(),
                        Path::new(&format!("{immutable_file_number:0>5}.secondary")).to_path_buf(),
                    ]
                })
                .collect::<Vec<_>>();
            let digest = self.digest.read().await.clone();

            Ok(ComputedImmutablesDigests::compute_immutables_digests(
                BTreeMap::from_iter(immutable_file_paths.into_iter().map(|immutable_file_path| {
                    (
                        ImmutableFile::new(immutable_file_path).unwrap(),
                        Some(digest.clone()),
                    )
                })),
                slog::Logger::root(slog::Discard, slog::o!()),
            )?)
        } else {
            Err(ImmutableDigesterError::NotEnoughImmutable {
                expected_number: *range.end(),
                found_number: None,
                db_dir: dirpath.to_owned(),
            })
        }
    }

    async fn compute_merkle_tree(
        &self,
        dirpath: &Path,
        beacon: &CardanoDbBeacon,
    ) -> Result<MKTree<MKTreeStoreInMemory>, ImmutableDigesterError> {
        if self.is_success {
            let leaves = self.mktree_leaves.read().await;
            Ok(MKTree::new(&leaves).unwrap())
        } else {
            Err(ImmutableDigesterError::NotEnoughImmutable {
                expected_number: beacon.immutable_file_number,
                found_number: None,
                db_dir: dirpath.to_owned(),
            })
        }
    }
}