1mod blockstore_with_read_cache;
5mod blockstore_with_write_buffer;
6pub mod car;
7mod db_impl;
8mod db_mode;
9mod either;
10pub mod gc;
11mod memory;
12pub mod migration;
13pub mod parity_db;
14pub mod parity_db_config;
15pub mod ttl;
16
17pub use blockstore_with_read_cache::*;
18pub use blockstore_with_write_buffer::BlockstoreWithWriteBuffer;
19pub use db_impl::DbImpl;
20pub use either::Either;
21pub use fvm_ipld_blockstore::{Blockstore, MemoryBlockstore};
22pub use memory::{IndexMapBlockstore, MemoryDB};
23
24use crate::blocks::{Tipset, TipsetKey};
25use crate::prelude::*;
26use crate::rpc::eth::types::EthHash;
27use ambassador::delegatable_trait;
28use serde::Serialize;
29use serde::de::DeserializeOwned;
30
31pub const CAR_DB_DIR_NAME: &str = "car_db";
32
33pub mod setting_keys {
34 pub const HEAD_KEY: &str = "head";
36 pub const MPOOL_CONFIG_KEY: &str = "/mpool/config";
38}
39
40#[auto_impl::auto_impl(&, Arc)]
43#[delegatable_trait]
44pub trait SettingsStore {
45 fn read_bin(&self, key: &str) -> anyhow::Result<Option<Vec<u8>>>;
48
49 fn write_bin(&self, key: &str, value: &[u8]) -> anyhow::Result<()>;
52
53 fn exists(&self, key: &str) -> anyhow::Result<bool>;
55
56 #[allow(dead_code)]
58 fn setting_keys(&self) -> anyhow::Result<Vec<String>>;
59}
60
61pub trait SettingsStoreExt {
65 fn read_obj<V: DeserializeOwned>(&self, key: &str) -> anyhow::Result<Option<V>>;
66 fn write_obj<V: Serialize>(&self, key: &str, value: &V) -> anyhow::Result<()>;
67
68 #[allow(dead_code)]
69 fn require_obj<V: DeserializeOwned>(&self, key: &str) -> anyhow::Result<V>;
71}
72
73impl<T: ?Sized + SettingsStore> SettingsStoreExt for T {
74 fn read_obj<V: DeserializeOwned>(&self, key: &str) -> anyhow::Result<Option<V>> {
75 match self.read_bin(key)? {
76 Some(bytes) => Ok(Some(serde_json::from_slice(&bytes)?)),
77 None => Ok(None),
78 }
79 }
80
81 fn write_obj<V: Serialize>(&self, key: &str, value: &V) -> anyhow::Result<()> {
82 self.write_bin(key, &serde_json::to_vec(value)?)
83 }
84
85 fn require_obj<V: DeserializeOwned>(&self, key: &str) -> anyhow::Result<V> {
86 self.read_bin(key)?
87 .with_context(|| format!("Key {key} not found"))
88 .and_then(|bytes| serde_json::from_slice(&bytes).map_err(Into::into))
89 }
90}
91
92#[auto_impl::auto_impl(&, Arc)]
95#[delegatable_trait]
96pub trait EthMappingsStore {
97 fn read_bin(&self, key: &EthHash) -> anyhow::Result<Option<Vec<u8>>>;
100
101 fn write_bin(&self, key: &EthHash, value: &[u8]) -> anyhow::Result<()>;
104
105 #[allow(dead_code)]
107 fn exists(&self, key: &EthHash) -> anyhow::Result<bool>;
108
109 fn get_message_cids(&self) -> anyhow::Result<Vec<(Cid, u64)>>;
111
112 fn delete(&self, keys: Vec<EthHash>) -> anyhow::Result<()>;
114
115 fn tipset_key_by_epoch(&self, epoch: ChainEpoch) -> anyhow::Result<Option<TipsetKey>>;
117
118 fn delete_tipset_key_at_epoch(&self, epoch: ChainEpoch) -> anyhow::Result<()>;
120
121 fn set_tipset_key_at_epoch_raw(&self, epoch: ChainEpoch, tsk: &TipsetKey)
123 -> anyhow::Result<()>;
124
125 fn set_tipset_key_at_epoch(&self, ts: &Tipset) -> anyhow::Result<()> {
127 EthMappingsStore::set_tipset_key_at_epoch_raw(self, ts.epoch(), ts.key())
128 }
129}
130
131pub trait EthMappingsStoreExt {
132 fn read_obj<V: DeserializeOwned>(&self, key: &EthHash) -> anyhow::Result<Option<V>>;
133 fn write_obj<V: Serialize>(&self, key: &EthHash, value: &V) -> anyhow::Result<()>;
134}
135
136impl<T: ?Sized + EthMappingsStore> EthMappingsStoreExt for T {
137 fn read_obj<V: DeserializeOwned>(&self, key: &EthHash) -> anyhow::Result<Option<V>> {
138 match self.read_bin(key)? {
139 Some(bytes) => Ok(Some(fvm_ipld_encoding::from_slice(&bytes)?)),
140 None => Ok(None),
141 }
142 }
143
144 fn write_obj<V: Serialize>(&self, key: &EthHash, value: &V) -> anyhow::Result<()> {
145 self.write_bin(key, &fvm_ipld_encoding::to_vec(value)?)
146 }
147}
148
149pub trait DBStatistics {
151 fn get_statistics(&self) -> Option<String> {
152 None
153 }
154}
155
156impl<DB: DBStatistics> DBStatistics for std::sync::Arc<DB> {
157 fn get_statistics(&self) -> Option<String> {
158 self.as_ref().get_statistics()
159 }
160}
161
162#[auto_impl::auto_impl(&, Arc)]
164pub trait PersistentStore: Blockstore {
165 fn put_keyed_persistent(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()>;
172}
173
174impl PersistentStore for MemoryBlockstore {
175 fn put_keyed_persistent(&self, k: &Cid, block: &[u8]) -> anyhow::Result<()> {
176 self.put_keyed(k, block)
177 }
178}
179
180#[auto_impl::auto_impl(&, Arc)]
181#[delegatable_trait]
182pub trait HeaviestTipsetKeyProvider {
183 fn heaviest_tipset_key(&self) -> anyhow::Result<Option<TipsetKey>>;
185
186 fn set_heaviest_tipset_key(&self, tsk: &TipsetKey) -> anyhow::Result<()>;
188}
189
190#[auto_impl::auto_impl(&, Arc)]
191pub trait BlockstoreWriteOpsSubscribable {
192 fn subscribe_write_ops(
193 &self,
194 ) -> anyhow::Result<tokio::sync::broadcast::Receiver<Vec<(Cid, bytes::Bytes)>>>;
195
196 fn unsubscribe_write_ops(&self);
197}
198
199pub mod db_engine {
200 use std::path::{Path, PathBuf};
201
202 use super::db_mode::choose_db;
203
204 pub type Db = crate::db::parity_db::ParityDb;
205 pub type DbConfig = crate::db::parity_db_config::ParityDbConfig;
206
207 pub fn db_root(chain_data_root: &Path) -> anyhow::Result<PathBuf> {
209 choose_db(chain_data_root)
210 }
211
212 pub fn open_db(path: PathBuf, config: &DbConfig) -> anyhow::Result<Db> {
213 Db::open(path, config)
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 pub mod db_utils;
220 mod mem_test;
221 mod parity_test;
222 pub mod subtests;
223}