Skip to main content

phos_data_network/
database.rs

1#[cfg(not(target_arch = "wasm32"))]
2use std::{
3    fs,
4    io::{Read, Write},
5    path::PathBuf,
6};
7
8#[cfg(not(target_arch = "wasm32"))]
9use cometbft::hash::Algorithm;
10use eyre::Result;
11#[cfg(not(target_arch = "wasm32"))]
12use helios_exex_light_client::types::{Hash, Height};
13
14use crate::config::{Config, TrustOptions};
15
16pub trait Database: Clone + Sync + Send + 'static {
17    fn new(config: &Config) -> Result<Self>
18    where
19        Self: Sized;
20
21    fn save_trust_options(&self, trust_options: &TrustOptions) -> Result<()>;
22    fn load_trust_options(&self) -> Result<TrustOptions>;
23}
24
25#[cfg(not(target_arch = "wasm32"))]
26#[derive(Clone)]
27pub struct FileDB {
28    data_dir: PathBuf,
29    default_trust_options: Option<TrustOptions>,
30}
31
32#[cfg(not(target_arch = "wasm32"))]
33impl Database for FileDB {
34    fn new(config: &Config) -> Result<Self> {
35        if let Some(data_dir) = &config.data_dir {
36            return Ok(Self {
37                data_dir: data_dir.to_path_buf(),
38                default_trust_options: config.trust_options.clone(),
39            });
40        }
41
42        eyre::bail!("data dir not in config")
43    }
44
45    fn save_trust_options(&self, trust_options: &TrustOptions) -> Result<()> {
46        fs::create_dir_all(&self.data_dir)?;
47
48        let mut file = fs::OpenOptions::new()
49            .write(true)
50            .create(true)
51            .truncate(true)
52            .open(self.data_dir.join("trust_options"))?;
53
54        file.write_all(&trust_options.height.value().to_be_bytes())?;
55        file.write_all(trust_options.hash.as_bytes())?;
56
57        Ok(())
58    }
59
60    fn load_trust_options(&self) -> Result<TrustOptions> {
61        let mut buf = Vec::new();
62
63        let result = fs::OpenOptions::new()
64            .read(true)
65            .open(self.data_dir.join("trust_options"))
66            .map(|mut file| file.read_to_end(&mut buf));
67
68        if buf.len() == 40 && result.is_ok() {
69            let height = Height::try_from(u64::from_be_bytes(buf[..8].try_into()?))?;
70            let hash = Hash::from_bytes(Algorithm::Sha256, &buf[8..])?;
71
72            Ok(TrustOptions { height, hash })
73        } else {
74            self.default_trust_options
75                .clone()
76                .ok_or_else(|| eyre::eyre!("trust options not found"))
77        }
78    }
79}
80
81#[derive(Clone)]
82pub struct ConfigDB {
83    trust_options: TrustOptions,
84}
85
86impl Database for ConfigDB {
87    fn new(config: &Config) -> Result<Self> {
88        let trust_options = config
89            .trust_options
90            .clone()
91            .ok_or_else(|| eyre::eyre!("CometBFT trust height and hash are required"))?;
92
93        Ok(Self { trust_options })
94    }
95
96    fn save_trust_options(&self, _trust_options: &TrustOptions) -> Result<()> {
97        Ok(())
98    }
99
100    fn load_trust_options(&self) -> Result<TrustOptions> {
101        Ok(self.trust_options.clone())
102    }
103}