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
use async_trait::async_trait;
use cnidarium::{RootHash, Snapshot};
use sha2::{Digest as _, Sha256};

static APPHASH_DOMSEP: &str = "FilamentAppHash";

#[derive(Clone, Copy, Eq, PartialEq)]
pub struct AppHash(pub [u8; 32]);

impl From<RootHash> for AppHash {
    fn from(value: RootHash) -> Self {
        let mut h = Sha256::new();
        h.update(APPHASH_DOMSEP);
        h.update(value.0);

        AppHash(h.finalize().into())
    }
}

impl std::fmt::Debug for AppHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("AppHash")
            .field(&hex::encode(self.0))
            .finish()
    }
}

#[async_trait]
pub trait AppHashRead {
    async fn app_hash(&self) -> eyre::Result<AppHash>;
}

#[async_trait]
impl AppHashRead for Snapshot {
    async fn app_hash(&self) -> eyre::Result<AppHash> {
        let root = self.root_hash().await.map_err(|err| eyre::eyre!(err))?;
        Ok(AppHash::from(root))
    }
}