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, Certificate2, 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
200pub trait UpdateAvailabilityStorage<Types>: Send
201where
202 Types: NodeType,
203{
204 fn insert_leaf(
205 &mut self,
206 leaf: &LeafQueryData<Types>,
207 ) -> impl Send + Future<Output = anyhow::Result<()>> {
208 self.insert_leaf_range([leaf])
209 }
210
211 fn insert_leaf_with_qc_chain(
212 &mut self,
213 leaf: &LeafQueryData<Types>,
214 qc_chain: Option<[CertificatePair<Types>; 2]>,
215 ) -> impl Send + Future<Output = anyhow::Result<()>> {
216 async move {
217 self.insert_leaf(leaf).await?;
218 self.insert_qc_chain(leaf.height(), qc_chain).await?;
219 Ok(())
220 }
221 }
222
223 fn insert_block(
224 &mut self,
225 block: &BlockQueryData<Types>,
226 ) -> impl Send + Future<Output = anyhow::Result<()>> {
227 self.insert_block_range([block])
228 }
229
230 fn insert_vid<'a>(
231 &mut self,
232 common: &'a VidCommonQueryData<Types>,
233 share: Option<&'a VidShare>,
234 ) -> impl Send + Future<Output = anyhow::Result<()>> {
235 self.insert_vid_range([(common, share)])
236 }
237
238 fn insert_qc_chain(
239 &mut self,
240 height: u64,
241 qc_chain: Option<[CertificatePair<Types>; 2]>,
242 ) -> impl Send + Future<Output = anyhow::Result<()>>;
243
244 fn insert_cert2(
245 &mut self,
246 height: u64,
247 cert2: Certificate2<Types>,
248 ) -> impl Send + Future<Output = anyhow::Result<()>>;
249
250 fn insert_leaf_range<'a>(
251 &mut self,
252 leaves: impl Send + IntoIterator<IntoIter: Send, Item = &'a LeafQueryData<Types>>,
253 ) -> impl Send + Future<Output = anyhow::Result<()>>;
254 fn insert_block_range<'a>(
255 &mut self,
256 blocks: impl Send + IntoIterator<IntoIter: Send, Item = &'a BlockQueryData<Types>>,
257 ) -> impl Send + Future<Output = anyhow::Result<()>>;
258 fn insert_vid_range<'a>(
259 &mut self,
260 vid: impl Send
261 + IntoIterator<
262 IntoIter: Send,
263 Item = (&'a VidCommonQueryData<Types>, Option<&'a VidShare>),
264 >,
265 ) -> impl Send + Future<Output = anyhow::Result<()>>;
266}
267
268#[async_trait]
269pub trait NodeStorage<Types>
270where
271 Types: NodeType,
272 Header<Types>: QueryableHeader<Types>,
273{
274 async fn block_height(&mut self) -> QueryResult<usize>;
275 async fn count_transactions_in_range(
276 &mut self,
277 range: impl RangeBounds<usize> + Send,
278 namespace: Option<NamespaceId<Types>>,
279 ) -> QueryResult<usize>;
280 async fn payload_size_in_range(
281 &mut self,
282 range: impl RangeBounds<usize> + Send,
283 namespace: Option<NamespaceId<Types>>,
284 ) -> QueryResult<usize>;
285 async fn vid_share<ID>(&mut self, id: ID) -> QueryResult<VidShare>
286 where
287 ID: Into<BlockId<Types>> + Send + Sync;
288 async fn get_header_window(
289 &mut self,
290 start: impl Into<WindowStart<Types>> + Send + Sync,
291 end: u64,
292 limit: usize,
293 ) -> QueryResult<TimeWindowQueryData<Header<Types>>>;
294
295 async fn latest_qc_chain(&mut self) -> QueryResult<Option<[CertificatePair<Types>; 2]>>;
296
297 async fn load_cert2(&mut self, height: u64) -> QueryResult<Option<Certificate2<Types>>>;
298
299 async fn load_earliest_cert2(
304 &mut self,
305 height: u64,
306 ) -> QueryResult<Option<Certificate2<Types>>>;
307
308 async fn sync_status_for_range(
310 &mut self,
311 from: usize,
312 to: usize,
313 ) -> QueryResult<SyncStatusQueryData>;
314}
315
316#[derive(Clone, Debug, Default)]
317pub struct Aggregate<Types: NodeType>
318where
319 Header<Types>: QueryableHeader<Types>,
320{
321 pub height: i64,
322 pub num_transactions: HashMap<Option<NamespaceId<Types>>, usize>,
323 pub payload_size: HashMap<Option<NamespaceId<Types>>, usize>,
324}
325
326pub trait AggregatesStorage<Types>
327where
328 Types: NodeType,
329 Header<Types>: QueryableHeader<Types>,
330{
331 fn aggregates_height(&mut self) -> impl Future<Output = anyhow::Result<usize>> + Send;
333
334 fn load_prev_aggregate(
336 &mut self,
337 ) -> impl Future<Output = anyhow::Result<Option<Aggregate<Types>>>> + Send;
338}
339
340pub trait UpdateAggregatesStorage<Types>
341where
342 Types: NodeType,
343 Header<Types>: QueryableHeader<Types>,
344{
345 fn update_aggregates(
347 &mut self,
348 aggregate: Aggregate<Types>,
349 blocks: &[PayloadMetadata<Types>],
350 ) -> impl Future<Output = anyhow::Result<Aggregate<Types>>> + Send;
351}
352
353#[async_trait]
363pub trait ExplorerStorage<Types>
364where
365 Types: NodeType,
366 Header<Types>: ExplorerHeader<Types> + QueryableHeader<Types>,
367 Transaction<Types>: ExplorerTransaction<Types>,
368 Payload<Types>: QueryablePayload<Types>,
369{
370 async fn get_block_detail(
374 &mut self,
375 request: BlockIdentifier<Types>,
376 ) -> Result<BlockDetail<Types>, GetBlockDetailError>;
377
378 async fn get_block_summaries(
382 &mut self,
383 request: GetBlockSummariesRequest<Types>,
384 ) -> Result<Vec<BlockSummary<Types>>, GetBlockSummariesError>;
385
386 async fn get_transaction_detail(
390 &mut self,
391 request: TransactionIdentifier<Types>,
392 ) -> Result<TransactionDetailResponse<Types>, GetTransactionDetailError>;
393
394 async fn get_transaction_summaries(
398 &mut self,
399 request: GetTransactionSummariesRequest<Types>,
400 ) -> Result<Vec<TransactionSummary<Types>>, GetTransactionSummariesError>;
401
402 async fn get_explorer_summary(
406 &mut self,
407 ) -> Result<ExplorerSummary<Types>, GetExplorerSummaryError>;
408
409 async fn get_search_results(
413 &mut self,
414 query: TaggedBase64,
415 ) -> Result<SearchResult<Types>, GetSearchResultsError>;
416}
417
418#[async_trait]
421pub trait MerklizedStateStorage<Types, State, const ARITY: usize>
422where
423 Types: NodeType,
424 State: MerklizedState<Types, ARITY>,
425{
426 async fn get_path(
427 &mut self,
428 snapshot: Snapshot<Types, State, ARITY>,
429 key: State::Key,
430 ) -> QueryResult<MerkleProof<State::Entry, State::Key, State::T, ARITY>>;
431}
432
433#[async_trait]
434pub trait MerklizedStateHeightStorage {
435 async fn get_last_state_height(&mut self) -> QueryResult<usize>;
436}