lumina_node/
blockstore.rs1use blockstore::{Blockstore, Result};
4use celestia_types::sample::SAMPLE_ID_CODEC;
5use cid::CidGeneric;
6
7use crate::p2p::MAX_MH_SIZE;
8
9pub type InMemoryBlockstore = blockstore::InMemoryBlockstore<MAX_MH_SIZE>;
13
14#[cfg(not(target_arch = "wasm32"))]
15pub type RedbBlockstore = blockstore::RedbBlockstore;
19
20#[cfg(target_arch = "wasm32")]
21pub type IndexedDbBlockstore = blockstore::IndexedDbBlockstore;
25
26pub(crate) struct SampleBlockstore<B> {
28 blockstore: B,
29}
30
31impl<B> SampleBlockstore<B> {
32 pub(crate) fn new(blockstore: B) -> Self {
34 Self { blockstore }
35 }
36}
37
38impl<B> Blockstore for SampleBlockstore<B>
39where
40 B: Blockstore,
41{
42 async fn get<const S: usize>(&self, cid: &CidGeneric<S>) -> Result<Option<Vec<u8>>> {
43 self.blockstore.get(cid).await
44 }
45
46 async fn put_keyed<const S: usize>(&self, cid: &CidGeneric<S>, data: &[u8]) -> Result<()> {
47 if cid.codec() == SAMPLE_ID_CODEC {
48 self.blockstore.put_keyed(cid, data).await
49 } else {
50 Ok(())
51 }
52 }
53
54 async fn remove<const S: usize>(&self, cid: &CidGeneric<S>) -> Result<()> {
55 self.blockstore.remove(cid).await
56 }
57
58 async fn has<const S: usize>(&self, cid: &CidGeneric<S>) -> Result<bool> {
59 self.blockstore.has(cid).await
60 }
61
62 async fn close(self) -> Result<()> {
63 self.blockstore.close().await
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use blockstore::Blockstore;
70 use celestia_types::{
71 nmt::Namespace, row::RowId, row_namespace_data::RowNamespaceDataId, sample::SampleId,
72 };
73 use lumina_utils::test_utils::async_test;
74
75 use super::{InMemoryBlockstore, SampleBlockstore};
76
77 #[async_test]
78 async fn should_only_store_samples() {
79 macro_rules! cid {
80 ($bytes:expr) => {
81 ::cid::CidGeneric::try_from($bytes).unwrap()
82 };
83 ($id:ty, $($args:expr),+ $(,)?) => {
84 $crate::p2p::shwap::convert_cid(
85 &<$id>::new($($args),+).unwrap().into()
86 )
87 .unwrap()
88 };
89 }
90
91 let blockstore = SampleBlockstore::new(InMemoryBlockstore::new());
92
93 let sample_cids = [
94 cid!(SampleId, 1, 2, 3),
95 cid!(SampleId, 1111, 232, 33),
96 cid!(SampleId, 123, 1, 888888888),
97 ];
98
99 let non_sample_cids = [
100 cid!(RowId, 1, 1737),
101 cid!(RowId, 8812, 193139),
102 cid!(RowNamespaceDataId, Namespace::new_v0(b"a").unwrap(), 15, 12),
103 cid!(RowNamespaceDataId, Namespace::new_v0(b"z").unwrap(), 1, 1),
104 cid!([1; 64].as_ref()),
105 cid!([[1].as_ref(), &[18; 63]].concat()),
106 ];
107
108 for cid in sample_cids.iter().chain(non_sample_cids.iter()) {
109 blockstore.put_keyed(cid, &[10; 150]).await.unwrap();
110 }
111
112 for cid in &sample_cids {
113 assert!(blockstore.has(cid).await.unwrap());
114 }
115 for cid in &non_sample_cids {
116 assert!(!blockstore.has(cid).await.unwrap());
117 }
118 }
119}