mithril_cardano_node_internal_database/signable_builder/
cardano_database.rs

1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3
4use anyhow::Context;
5use async_trait::async_trait;
6use slog::{Logger, info};
7
8use mithril_common::{
9    StdResult,
10    entities::{CardanoDbBeacon, ProtocolMessage, ProtocolMessagePartKey},
11    logging::LoggerExtensions,
12    signable_builder::SignableBuilder,
13};
14
15use crate::digesters::ImmutableDigester;
16
17/// This structure is responsible for calculating the message for incremental Cardano database.
18pub struct CardanoDatabaseSignableBuilder {
19    digester: Arc<dyn ImmutableDigester>,
20    logger: Logger,
21    dirpath: PathBuf,
22}
23
24impl CardanoDatabaseSignableBuilder {
25    /// Constructor
26    pub fn new(digester: Arc<dyn ImmutableDigester>, dirpath: &Path, logger: Logger) -> Self {
27        Self {
28            digester,
29            logger: logger.new_with_component_name::<Self>(),
30            dirpath: dirpath.to_owned(),
31        }
32    }
33}
34
35#[async_trait]
36impl SignableBuilder<CardanoDbBeacon> for CardanoDatabaseSignableBuilder {
37    async fn compute_protocol_message(
38        &self,
39        beacon: CardanoDbBeacon,
40    ) -> StdResult<ProtocolMessage> {
41        let merkle_tree = self
42            .digester
43            .compute_merkle_tree(&self.dirpath, &beacon)
44            .await
45            .with_context(|| {
46                format!(
47                    "Cardano Database Signable Builder can not compute merkle tree of '{}'",
48                    &self.dirpath.display()
49                )
50            })?;
51
52        let merkle_root = merkle_tree.compute_root()?.to_hex();
53        info!(
54            self.logger,
55            "Computed Cardano database Merkle root = '{merkle_root}'"
56        );
57
58        let mut protocol_message = ProtocolMessage::new();
59        protocol_message.set_message_part(
60            ProtocolMessagePartKey::CardanoDatabaseMerkleRoot,
61            merkle_root,
62        );
63
64        Ok(protocol_message)
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use mithril_common::crypto_helper::{MKTree, MKTreeStoreInMemory};
71
72    use crate::test::TestLogger;
73    use crate::test::double::DumbImmutableDigester;
74
75    use super::*;
76
77    #[tokio::test]
78    async fn compute_signable() {
79        let digests = vec!["digest-1".to_string(), "digest-2".to_string()];
80        let digester = DumbImmutableDigester::default().with_merkle_tree(digests.clone());
81        let signable_builder = CardanoDatabaseSignableBuilder::new(
82            Arc::new(digester),
83            Path::new(""),
84            TestLogger::stdout(),
85        );
86
87        let protocol_message = signable_builder
88            .compute_protocol_message(CardanoDbBeacon::default())
89            .await
90            .unwrap();
91
92        let expected_mktree: MKTree<MKTreeStoreInMemory> = MKTree::new(&digests).unwrap();
93        let mut expected_message = ProtocolMessage::new();
94        expected_message.set_message_part(
95            ProtocolMessagePartKey::CardanoDatabaseMerkleRoot,
96            expected_mktree.compute_root().unwrap().to_hex(),
97        );
98        assert_eq!(expected_message, protocol_message);
99    }
100}