phos_data_network/
database.rs1#[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 phos_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}