1use std::ops::RangeBounds;
60
61use alloy::primitives::map::HashMap;
62use async_trait::async_trait;
63use futures::future::Future;
64use hotshot_types::{
65 data::VidShare, simple_certificate::CertificatePair, traits::node_implementation::NodeType,
66};
67use jf_merkle_tree_compat::prelude::MerkleProof;
68use tagged_base64::TaggedBase64;
69
70use crate::{
71 Header, Payload, QueryResult, Transaction,
72 availability::{
73 BlockId, BlockQueryData, LeafId, LeafQueryData, NamespaceId, PayloadMetadata,
74 PayloadQueryData, QueryableHeader, QueryablePayload, TransactionHash, VidCommonMetadata,
75 VidCommonQueryData,
76 },
77 explorer::{
78 query_data::{
79 BlockDetail, BlockIdentifier, BlockSummary, ExplorerSummary, GetBlockDetailError,
80 GetBlockSummariesError, GetBlockSummariesRequest, GetExplorerSummaryError,
81 GetSearchResultsError, GetTransactionDetailError, GetTransactionSummariesError,
82 GetTransactionSummariesRequest, SearchResult, TransactionDetailResponse,
83 TransactionIdentifier, TransactionSummary,
84 },
85 traits::{ExplorerHeader, ExplorerTransaction},
86 },
87 merklized_state::{MerklizedState, Snapshot},
88 node::{SyncStatusQueryData, TimeWindowQueryData, WindowStart},
89 types::HeightIndexed,
90};
91
92pub mod fail_storage;
93pub mod fs;
94mod ledger_log;
95pub mod pruning;
96pub mod sql;
97
98#[cfg(any(test, feature = "testing"))]
99pub use fail_storage::FailStorage;
100#[cfg(feature = "file-system-data-source")]
101pub use fs::FileSystemStorage;
102#[cfg(feature = "sql-data-source")]
103pub use sql::{SqlStorage, StorageConnectionType};
104
105#[async_trait]
120pub trait AvailabilityStorage<Types>: Send + Sync
121where
122 Types: NodeType,
123 Header<Types>: QueryableHeader<Types>,
124 Payload<Types>: QueryablePayload<Types>,
125{
126 async fn get_leaf(&mut self, id: LeafId<Types>) -> QueryResult<LeafQueryData<Types>>;
127 async fn get_block(&mut self, id: BlockId<Types>) -> QueryResult<BlockQueryData<Types>>;
128 async fn get_header(&mut self, id: BlockId<Types>) -> QueryResult<Header<Types>>;
129 async fn get_payload(&mut self, id: BlockId<Types>) -> QueryResult<PayloadQueryData<Types>>;
130 async fn get_payload_metadata(
131 &mut self,
132 id: BlockId<Types>,
133 ) -> QueryResult<PayloadMetadata<Types>>;
134 async fn get_vid_common(
135 &mut self,
136 id: BlockId<Types>,
137 ) -> QueryResult<VidCommonQueryData<Types>>;
138 async fn get_vid_common_metadata(
139 &mut self,
140 id: BlockId<Types>,
141 ) -> QueryResult<VidCommonMetadata<Types>>;
142
143 async fn get_leaf_range<R>(
144 &mut self,
145 range: R,
146 ) -> QueryResult<Vec<QueryResult<LeafQueryData<Types>>>>
147 where
148 R: RangeBounds<usize> + Send + 'static;
149 async fn get_block_range<R>(
150 &mut self,
151 range: R,
152 ) -> QueryResult<Vec<QueryResult<BlockQueryData<Types>>>>
153 where
154 R: RangeBounds<usize> + Send + 'static;
155
156 async fn get_header_range<R>(
157 &mut self,
158 range: R,
159 ) -> QueryResult<Vec<QueryResult<Header<Types>>>>
160 where
161 R: RangeBounds<usize> + Send + 'static,
162 {
163 let blocks = self.get_block_range(range).await?;
164 Ok(blocks
165 .into_iter()
166 .map(|block| block.map(|block| block.header))
167 .collect())
168 }
169 async fn get_payload_range<R>(
170 &mut self,
171 range: R,
172 ) -> QueryResult<Vec<QueryResult<PayloadQueryData<Types>>>>
173 where
174 R: RangeBounds<usize> + Send + 'static;
175 async fn get_payload_metadata_range<R>(
176 &mut self,
177 range: R,
178 ) -> QueryResult<Vec<QueryResult<PayloadMetadata<Types>>>>
179 where
180 R: RangeBounds<usize> + Send + 'static;
181 async fn get_vid_common_range<R>(
182 &mut self,
183 range: R,
184 ) -> QueryResult<Vec<QueryResult<VidCommonQueryData<Types>>>>
185 where
186 R: RangeBounds<usize> + Send + 'static;
187 async fn get_vid_common_metadata_range<R>(
188 &mut self,
189 range: R,
190 ) -> QueryResult<Vec<QueryResult<VidCommonMetadata<Types>>>>
191 where
192 R: RangeBounds<usize> + Send + 'static;
193
194 async fn get_block_with_transaction(
195 &mut self,
196 hash: TransactionHash<Types>,
197 ) -> QueryResult<BlockQueryData<Types>>;
198
199 async fn first_available_leaf(&mut self, from: u64) -> QueryResult<LeafQueryData<Types>>;
201}
202
203pub trait UpdateAvailabilityStorage<Types>: Send
204where
205 Types: NodeType,
206{
207 fn insert_leaf(
208 &mut self,
209 leaf: &LeafQueryData<Types>,
210 ) -> impl Send + Future<Output = anyhow::Result<()>> {
211 self.insert_leaf_range([leaf])
212 }
213
214 fn insert_leaf_with_qc_chain(
215 &mut self,
216 leaf: &LeafQueryData<Types>,
217 qc_chain: Option<[CertificatePair<Types>; 2]>,
218 ) -> impl Send + Future<Output = anyhow::Result<()>> {
219 async move {
220 self.insert_leaf(leaf).await?;
221 self.insert_qc_chain(leaf.height(), qc_chain).await?;
222 Ok(())
223 }
224 }
225
226 fn insert_block(
227 &mut self,
228 block: &BlockQueryData<Types>,
229 ) -> impl Send + Future<Output = anyhow::Result<()>> {
230 self.insert_block_range([block])
231 }
232
233 fn insert_vid<'a>(
234 &mut self,
235 common: &'a VidCommonQueryData<Types>,
236 share: Option<&'a VidShare>,
237 ) -> impl Send + Future<Output = anyhow::Result<()>> {
238 self.insert_vid_range([(common, share)])
239 }
240
241 fn insert_qc_chain(
242 &mut self,
243 height: u64,
244 qc_chain: Option<[CertificatePair<Types>; 2]>,
245 ) -> impl Send + Future<Output = anyhow::Result<()>>;
246 fn insert_leaf_range<'a>(
247 &mut self,
248 leaves: impl Send + IntoIterator<IntoIter: Send, Item = &'a LeafQueryData<Types>>,
249 ) -> impl Send + Future<Output = anyhow::Result<()>>;
250 fn insert_block_range<'a>(
251 &mut self,
252 blocks: impl Send + IntoIterator<IntoIter: Send, Item = &'a BlockQueryData<Types>>,
253 ) -> impl Send + Future<Output = anyhow::Result<()>>;
254 fn insert_vid_range<'a>(
255 &mut self,
256 vid: impl Send
257 + IntoIterator<
258 IntoIter: Send,
259 Item = (&'a VidCommonQueryData<Types>, Option<&'a VidShare>),
260 >,
261 ) -> impl Send + Future<Output = anyhow::Result<()>>;
262}
263
264#[async_trait]
265pub trait NodeStorage<Types>
266where
267 Types: NodeType,
268 Header<Types>: QueryableHeader<Types>,
269{
270 async fn block_height(&mut self) -> QueryResult<usize>;
271 async fn count_transactions_in_range(
272 &mut self,
273 range: impl RangeBounds<usize> + Send,
274 namespace: Option<NamespaceId<Types>>,
275 ) -> QueryResult<usize>;
276 async fn payload_size_in_range(
277 &mut self,
278 range: impl RangeBounds<usize> + Send,
279 namespace: Option<NamespaceId<Types>>,
280 ) -> QueryResult<usize>;
281 async fn vid_share<ID>(&mut self, id: ID) -> QueryResult<VidShare>
282 where
283 ID: Into<BlockId<Types>> + Send + Sync;
284 async fn get_header_window(
285 &mut self,
286 start: impl Into<WindowStart<Types>> + Send + Sync,
287 end: u64,
288 limit: usize,
289 ) -> QueryResult<TimeWindowQueryData<Header<Types>>>;
290
291 async fn latest_qc_chain(&mut self) -> QueryResult<Option<[CertificatePair<Types>; 2]>>;
292
293 async fn sync_status_for_range(
295 &mut self,
296 from: usize,
297 to: usize,
298 ) -> QueryResult<SyncStatusQueryData>;
299}
300
301#[derive(Clone, Debug, Default)]
302pub struct Aggregate<Types: NodeType>
303where
304 Header<Types>: QueryableHeader<Types>,
305{
306 pub height: i64,
307 pub num_transactions: HashMap<Option<NamespaceId<Types>>, usize>,
308 pub payload_size: HashMap<Option<NamespaceId<Types>>, usize>,
309}
310
311pub trait AggregatesStorage<Types>
312where
313 Types: NodeType,
314 Header<Types>: QueryableHeader<Types>,
315{
316 fn aggregates_height(&mut self) -> impl Future<Output = anyhow::Result<usize>> + Send;
318
319 fn load_prev_aggregate(
321 &mut self,
322 ) -> impl Future<Output = anyhow::Result<Option<Aggregate<Types>>>> + Send;
323}
324
325pub trait UpdateAggregatesStorage<Types>
326where
327 Types: NodeType,
328 Header<Types>: QueryableHeader<Types>,
329{
330 fn update_aggregates(
332 &mut self,
333 aggregate: Aggregate<Types>,
334 blocks: &[PayloadMetadata<Types>],
335 ) -> impl Future<Output = anyhow::Result<Aggregate<Types>>> + Send;
336}
337
338#[async_trait]
348pub trait ExplorerStorage<Types>
349where
350 Types: NodeType,
351 Header<Types>: ExplorerHeader<Types> + QueryableHeader<Types>,
352 Transaction<Types>: ExplorerTransaction<Types>,
353 Payload<Types>: QueryablePayload<Types>,
354{
355 async fn get_block_detail(
359 &mut self,
360 request: BlockIdentifier<Types>,
361 ) -> Result<BlockDetail<Types>, GetBlockDetailError>;
362
363 async fn get_block_summaries(
367 &mut self,
368 request: GetBlockSummariesRequest<Types>,
369 ) -> Result<Vec<BlockSummary<Types>>, GetBlockSummariesError>;
370
371 async fn get_transaction_detail(
375 &mut self,
376 request: TransactionIdentifier<Types>,
377 ) -> Result<TransactionDetailResponse<Types>, GetTransactionDetailError>;
378
379 async fn get_transaction_summaries(
383 &mut self,
384 request: GetTransactionSummariesRequest<Types>,
385 ) -> Result<Vec<TransactionSummary<Types>>, GetTransactionSummariesError>;
386
387 async fn get_explorer_summary(
391 &mut self,
392 ) -> Result<ExplorerSummary<Types>, GetExplorerSummaryError>;
393
394 async fn get_search_results(
398 &mut self,
399 query: TaggedBase64,
400 ) -> Result<SearchResult<Types>, GetSearchResultsError>;
401}
402
403#[async_trait]
406pub trait MerklizedStateStorage<Types, State, const ARITY: usize>
407where
408 Types: NodeType,
409 State: MerklizedState<Types, ARITY>,
410{
411 async fn get_path(
412 &mut self,
413 snapshot: Snapshot<Types, State, ARITY>,
414 key: State::Key,
415 ) -> QueryResult<MerkleProof<State::Entry, State::Key, State::T, ARITY>>;
416}
417
418#[async_trait]
419pub trait MerklizedStateHeightStorage {
420 async fn get_last_state_height(&mut self) -> QueryResult<usize>;
421}