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 availability::{
72 BlockId, BlockQueryData, LeafId, LeafQueryData, NamespaceId, PayloadMetadata,
73 PayloadQueryData, QueryableHeader, QueryablePayload, TransactionHash, VidCommonMetadata,
74 VidCommonQueryData,
75 },
76 explorer::{
77 query_data::{
78 BlockDetail, BlockIdentifier, BlockSummary, ExplorerSummary, GetBlockDetailError,
79 GetBlockSummariesError, GetBlockSummariesRequest, GetExplorerSummaryError,
80 GetSearchResultsError, GetTransactionDetailError, GetTransactionSummariesError,
81 GetTransactionSummariesRequest, SearchResult, TransactionDetailResponse,
82 TransactionIdentifier, TransactionSummary,
83 },
84 traits::{ExplorerHeader, ExplorerTransaction},
85 },
86 merklized_state::{MerklizedState, Snapshot},
87 node::{SyncStatus, TimeWindowQueryData, WindowStart},
88 Header, Payload, QueryResult, Transaction,
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(&mut self) -> QueryResult<SyncStatus>;
260}
261
262#[derive(Clone, Debug, Default)]
263pub struct Aggregate<Types: NodeType>
264where
265 Header<Types>: QueryableHeader<Types>,
266{
267 pub height: i64,
268 pub num_transactions: HashMap<Option<NamespaceId<Types>>, usize>,
269 pub payload_size: HashMap<Option<NamespaceId<Types>>, usize>,
270}
271
272pub trait AggregatesStorage<Types>
273where
274 Types: NodeType,
275 Header<Types>: QueryableHeader<Types>,
276{
277 fn aggregates_height(&mut self) -> impl Future<Output = anyhow::Result<usize>> + Send;
279
280 fn load_prev_aggregate(
282 &mut self,
283 ) -> impl Future<Output = anyhow::Result<Option<Aggregate<Types>>>> + Send;
284}
285
286pub trait UpdateAggregatesStorage<Types>
287where
288 Types: NodeType,
289 Header<Types>: QueryableHeader<Types>,
290{
291 fn update_aggregates(
293 &mut self,
294 aggregate: Aggregate<Types>,
295 blocks: &[PayloadMetadata<Types>],
296 ) -> impl Future<Output = anyhow::Result<Aggregate<Types>>> + Send;
297}
298
299#[async_trait]
309pub trait ExplorerStorage<Types>
310where
311 Types: NodeType,
312 Header<Types>: ExplorerHeader<Types> + QueryableHeader<Types>,
313 Transaction<Types>: ExplorerTransaction<Types>,
314 Payload<Types>: QueryablePayload<Types>,
315{
316 async fn get_block_detail(
320 &mut self,
321 request: BlockIdentifier<Types>,
322 ) -> Result<BlockDetail<Types>, GetBlockDetailError>;
323
324 async fn get_block_summaries(
328 &mut self,
329 request: GetBlockSummariesRequest<Types>,
330 ) -> Result<Vec<BlockSummary<Types>>, GetBlockSummariesError>;
331
332 async fn get_transaction_detail(
336 &mut self,
337 request: TransactionIdentifier<Types>,
338 ) -> Result<TransactionDetailResponse<Types>, GetTransactionDetailError>;
339
340 async fn get_transaction_summaries(
344 &mut self,
345 request: GetTransactionSummariesRequest<Types>,
346 ) -> Result<Vec<TransactionSummary<Types>>, GetTransactionSummariesError>;
347
348 async fn get_explorer_summary(
352 &mut self,
353 ) -> Result<ExplorerSummary<Types>, GetExplorerSummaryError>;
354
355 async fn get_search_results(
359 &mut self,
360 query: TaggedBase64,
361 ) -> Result<SearchResult<Types>, GetSearchResultsError>;
362}
363
364#[async_trait]
367pub trait MerklizedStateStorage<Types, State, const ARITY: usize>
368where
369 Types: NodeType,
370 State: MerklizedState<Types, ARITY>,
371{
372 async fn get_path(
373 &mut self,
374 snapshot: Snapshot<Types, State, ARITY>,
375 key: State::Key,
376 ) -> QueryResult<MerkleProof<State::Entry, State::Key, State::T, ARITY>>;
377}
378
379#[async_trait]
380pub trait MerklizedStateHeightStorage {
381 async fn get_last_state_height(&mut self) -> QueryResult<usize>;
382}