hotshot_query_service/data_source/
storage.rs1use 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};
90
91pub mod fail_storage;
92pub mod fs;
93mod ledger_log;
94pub mod pruning;
95pub mod sql;
96
97#[cfg(any(test, feature = "testing"))]
98pub use fail_storage::FailStorage;
99#[cfg(feature = "file-system-data-source")]
100pub use fs::FileSystemStorage;
101#[cfg(feature = "sql-data-source")]
102pub use sql::{SqlStorage, StorageConnectionType};
103
104#[async_trait]
119pub trait AvailabilityStorage<Types>: Send + Sync
120where
121 Types: NodeType,
122 Header<Types>: QueryableHeader<Types>,
123 Payload<Types>: QueryablePayload<Types>,
124{
125 async fn get_leaf(&mut self, id: LeafId<Types>) -> QueryResult<LeafQueryData<Types>>;
126 async fn get_block(&mut self, id: BlockId<Types>) -> QueryResult<BlockQueryData<Types>>;
127 async fn get_header(&mut self, id: BlockId<Types>) -> QueryResult<Header<Types>>;
128 async fn get_payload(&mut self, id: BlockId<Types>) -> QueryResult<PayloadQueryData<Types>>;
129 async fn get_payload_metadata(
130 &mut self,
131 id: BlockId<Types>,
132 ) -> QueryResult<PayloadMetadata<Types>>;
133 async fn get_vid_common(
134 &mut self,
135 id: BlockId<Types>,
136 ) -> QueryResult<VidCommonQueryData<Types>>;
137 async fn get_vid_common_metadata(
138 &mut self,
139 id: BlockId<Types>,
140 ) -> QueryResult<VidCommonMetadata<Types>>;
141
142 async fn get_leaf_range<R>(
143 &mut self,
144 range: R,
145 ) -> QueryResult<Vec<QueryResult<LeafQueryData<Types>>>>
146 where
147 R: RangeBounds<usize> + Send + 'static;
148 async fn get_block_range<R>(
149 &mut self,
150 range: R,
151 ) -> QueryResult<Vec<QueryResult<BlockQueryData<Types>>>>
152 where
153 R: RangeBounds<usize> + Send + 'static;
154
155 async fn get_header_range<R>(
156 &mut self,
157 range: R,
158 ) -> QueryResult<Vec<QueryResult<Header<Types>>>>
159 where
160 R: RangeBounds<usize> + Send + 'static,
161 {
162 let blocks = self.get_block_range(range).await?;
163 Ok(blocks
164 .into_iter()
165 .map(|block| block.map(|block| block.header))
166 .collect())
167 }
168 async fn get_payload_range<R>(
169 &mut self,
170 range: R,
171 ) -> QueryResult<Vec<QueryResult<PayloadQueryData<Types>>>>
172 where
173 R: RangeBounds<usize> + Send + 'static;
174 async fn get_payload_metadata_range<R>(
175 &mut self,
176 range: R,
177 ) -> QueryResult<Vec<QueryResult<PayloadMetadata<Types>>>>
178 where
179 R: RangeBounds<usize> + Send + 'static;
180 async fn get_vid_common_range<R>(
181 &mut self,
182 range: R,
183 ) -> QueryResult<Vec<QueryResult<VidCommonQueryData<Types>>>>
184 where
185 R: RangeBounds<usize> + Send + 'static;
186 async fn get_vid_common_metadata_range<R>(
187 &mut self,
188 range: R,
189 ) -> QueryResult<Vec<QueryResult<VidCommonMetadata<Types>>>>
190 where
191 R: RangeBounds<usize> + Send + 'static;
192
193 async fn get_block_with_transaction(
194 &mut self,
195 hash: TransactionHash<Types>,
196 ) -> QueryResult<BlockQueryData<Types>>;
197
198 async fn first_available_leaf(&mut self, from: u64) -> QueryResult<LeafQueryData<Types>>;
200}
201
202pub trait UpdateAvailabilityStorage<Types>
203where
204 Types: NodeType,
205{
206 fn insert_leaf(
207 &mut self,
208 leaf: LeafQueryData<Types>,
209 ) -> impl Send + Future<Output = anyhow::Result<()>> {
210 self.insert_leaf_with_qc_chain(leaf, None)
211 }
212
213 fn insert_leaf_with_qc_chain(
214 &mut self,
215 leaf: LeafQueryData<Types>,
216 qc_chain: Option<[CertificatePair<Types>; 2]>,
217 ) -> impl Send + Future<Output = anyhow::Result<()>>;
218 fn insert_block(
219 &mut self,
220 block: BlockQueryData<Types>,
221 ) -> impl Send + Future<Output = anyhow::Result<()>>;
222 fn insert_vid(
223 &mut self,
224 common: VidCommonQueryData<Types>,
225 share: Option<VidShare>,
226 ) -> impl Send + Future<Output = anyhow::Result<()>>;
227}
228
229#[async_trait]
230pub trait NodeStorage<Types>
231where
232 Types: NodeType,
233 Header<Types>: QueryableHeader<Types>,
234{
235 async fn block_height(&mut self) -> QueryResult<usize>;
236 async fn count_transactions_in_range(
237 &mut self,
238 range: impl RangeBounds<usize> + Send,
239 namespace: Option<NamespaceId<Types>>,
240 ) -> QueryResult<usize>;
241 async fn payload_size_in_range(
242 &mut self,
243 range: impl RangeBounds<usize> + Send,
244 namespace: Option<NamespaceId<Types>>,
245 ) -> QueryResult<usize>;
246 async fn vid_share<ID>(&mut self, id: ID) -> QueryResult<VidShare>
247 where
248 ID: Into<BlockId<Types>> + Send + Sync;
249 async fn get_header_window(
250 &mut self,
251 start: impl Into<WindowStart<Types>> + Send + Sync,
252 end: u64,
253 limit: usize,
254 ) -> QueryResult<TimeWindowQueryData<Header<Types>>>;
255
256 async fn latest_qc_chain(&mut self) -> QueryResult<Option<[CertificatePair<Types>; 2]>>;
257
258 async fn sync_status_for_range(
260 &mut self,
261 from: usize,
262 to: usize,
263 ) -> QueryResult<SyncStatusQueryData>;
264}
265
266#[derive(Clone, Debug, Default)]
267pub struct Aggregate<Types: NodeType>
268where
269 Header<Types>: QueryableHeader<Types>,
270{
271 pub height: i64,
272 pub num_transactions: HashMap<Option<NamespaceId<Types>>, usize>,
273 pub payload_size: HashMap<Option<NamespaceId<Types>>, usize>,
274}
275
276pub trait AggregatesStorage<Types>
277where
278 Types: NodeType,
279 Header<Types>: QueryableHeader<Types>,
280{
281 fn aggregates_height(&mut self) -> impl Future<Output = anyhow::Result<usize>> + Send;
283
284 fn load_prev_aggregate(
286 &mut self,
287 ) -> impl Future<Output = anyhow::Result<Option<Aggregate<Types>>>> + Send;
288}
289
290pub trait UpdateAggregatesStorage<Types>
291where
292 Types: NodeType,
293 Header<Types>: QueryableHeader<Types>,
294{
295 fn update_aggregates(
297 &mut self,
298 aggregate: Aggregate<Types>,
299 blocks: &[PayloadMetadata<Types>],
300 ) -> impl Future<Output = anyhow::Result<Aggregate<Types>>> + Send;
301}
302
303#[async_trait]
313pub trait ExplorerStorage<Types>
314where
315 Types: NodeType,
316 Header<Types>: ExplorerHeader<Types> + QueryableHeader<Types>,
317 Transaction<Types>: ExplorerTransaction<Types>,
318 Payload<Types>: QueryablePayload<Types>,
319{
320 async fn get_block_detail(
324 &mut self,
325 request: BlockIdentifier<Types>,
326 ) -> Result<BlockDetail<Types>, GetBlockDetailError>;
327
328 async fn get_block_summaries(
332 &mut self,
333 request: GetBlockSummariesRequest<Types>,
334 ) -> Result<Vec<BlockSummary<Types>>, GetBlockSummariesError>;
335
336 async fn get_transaction_detail(
340 &mut self,
341 request: TransactionIdentifier<Types>,
342 ) -> Result<TransactionDetailResponse<Types>, GetTransactionDetailError>;
343
344 async fn get_transaction_summaries(
348 &mut self,
349 request: GetTransactionSummariesRequest<Types>,
350 ) -> Result<Vec<TransactionSummary<Types>>, GetTransactionSummariesError>;
351
352 async fn get_explorer_summary(
356 &mut self,
357 ) -> Result<ExplorerSummary<Types>, GetExplorerSummaryError>;
358
359 async fn get_search_results(
363 &mut self,
364 query: TaggedBase64,
365 ) -> Result<SearchResult<Types>, GetSearchResultsError>;
366}
367
368#[async_trait]
371pub trait MerklizedStateStorage<Types, State, const ARITY: usize>
372where
373 Types: NodeType,
374 State: MerklizedState<Types, ARITY>,
375{
376 async fn get_path(
377 &mut self,
378 snapshot: Snapshot<Types, State, ARITY>,
379 key: State::Key,
380 ) -> QueryResult<MerkleProof<State::Entry, State::Key, State::T, ARITY>>;
381}
382
383#[async_trait]
384pub trait MerklizedStateHeightStorage {
385 async fn get_last_state_height(&mut self) -> QueryResult<usize>;
386}