1use crate::{
57 BlockData, ColdReceipt, ColdResult, ColdStorageBackend, ColdStorageRead, ColdStorageWrite,
58 Confirmed, Filter, HeaderSpecifier, ReceiptSpecifier, RpcLog, SignetEventsSpecifier,
59 StreamParams, TransactionSpecifier, ZenithHeaderSpecifier,
60};
61use alloy::primitives::BlockNumber;
62use signet_storage_types::{DbSignetEvent, DbZenithHeader, RecoveredTx, SealedHeader};
63use std::{future::Future, pin::Pin, sync::Arc, time::Duration};
64
65pub type StorageFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
68
69pub struct ErasedBackend(Arc<dyn DynColdStorageBackend>);
82
83impl ErasedBackend {
84 pub fn new<B: ColdStorageBackend>(backend: B) -> Self {
86 Self(Arc::new(backend))
87 }
88
89 pub const fn from_arc(arc: Arc<dyn DynColdStorageBackend>) -> Self {
95 Self(arc)
96 }
97
98 pub fn as_dyn(&self) -> &(dyn DynColdStorageBackend + 'static) {
100 &*self.0
101 }
102
103 pub fn into_arc(self) -> Arc<dyn DynColdStorageBackend> {
105 self.0
106 }
107}
108
109impl Clone for ErasedBackend {
110 fn clone(&self) -> Self {
111 Self(Arc::clone(&self.0))
112 }
113}
114
115impl std::fmt::Debug for ErasedBackend {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 f.debug_tuple("ErasedBackend").finish()
118 }
119}
120
121pub trait DynColdStorageBackend: Send + Sync + 'static {
127 fn dyn_get_header<'a>(
129 &'a self,
130 spec: HeaderSpecifier,
131 ) -> StorageFuture<'a, ColdResult<Option<SealedHeader>>>;
132
133 fn dyn_get_headers<'a>(
135 &'a self,
136 specs: Vec<HeaderSpecifier>,
137 ) -> StorageFuture<'a, ColdResult<Vec<Option<SealedHeader>>>>;
138
139 fn dyn_get_transaction<'a>(
141 &'a self,
142 spec: TransactionSpecifier,
143 ) -> StorageFuture<'a, ColdResult<Option<Confirmed<RecoveredTx>>>>;
144
145 fn dyn_get_transactions_in_block<'a>(
147 &'a self,
148 block: BlockNumber,
149 ) -> StorageFuture<'a, ColdResult<Vec<RecoveredTx>>>;
150
151 fn dyn_get_transaction_count<'a>(
153 &'a self,
154 block: BlockNumber,
155 ) -> StorageFuture<'a, ColdResult<u64>>;
156
157 fn dyn_get_receipt<'a>(
159 &'a self,
160 spec: ReceiptSpecifier,
161 ) -> StorageFuture<'a, ColdResult<Option<ColdReceipt>>>;
162
163 fn dyn_get_receipts_in_block<'a>(
165 &'a self,
166 block: BlockNumber,
167 ) -> StorageFuture<'a, ColdResult<Vec<ColdReceipt>>>;
168
169 fn dyn_get_signet_events<'a>(
171 &'a self,
172 spec: SignetEventsSpecifier,
173 ) -> StorageFuture<'a, ColdResult<Vec<DbSignetEvent>>>;
174
175 fn dyn_get_zenith_header<'a>(
177 &'a self,
178 spec: ZenithHeaderSpecifier,
179 ) -> StorageFuture<'a, ColdResult<Option<DbZenithHeader>>>;
180
181 fn dyn_get_zenith_headers<'a>(
183 &'a self,
184 spec: ZenithHeaderSpecifier,
185 ) -> StorageFuture<'a, ColdResult<Vec<DbZenithHeader>>>;
186
187 fn dyn_get_latest_block<'a>(&'a self) -> StorageFuture<'a, ColdResult<Option<BlockNumber>>>;
189
190 fn dyn_get_logs<'a>(
192 &'a self,
193 filter: &'a Filter,
194 max_logs: usize,
195 ) -> StorageFuture<'a, ColdResult<Vec<RpcLog>>>;
196
197 fn dyn_produce_log_stream<'a>(
199 &'a self,
200 filter: &'a Filter,
201 params: StreamParams,
202 ) -> StorageFuture<'a, ()>;
203
204 fn dyn_append_block<'a>(&'a self, data: BlockData) -> StorageFuture<'a, ColdResult<()>>;
206
207 fn dyn_append_blocks<'a>(&'a self, data: Vec<BlockData>) -> StorageFuture<'a, ColdResult<()>>;
209
210 fn dyn_truncate_above<'a>(&'a self, block: BlockNumber) -> StorageFuture<'a, ColdResult<()>>;
212
213 fn dyn_drain_above<'a>(
215 &'a self,
216 block: BlockNumber,
217 ) -> StorageFuture<'a, ColdResult<Vec<Vec<ColdReceipt>>>>;
218
219 fn dyn_read_timeout(&self) -> Option<Duration>;
221
222 fn dyn_write_timeout(&self) -> Option<Duration>;
224}
225
226impl<B: ColdStorageBackend> DynColdStorageBackend for B {
227 fn dyn_get_header<'a>(
228 &'a self,
229 spec: HeaderSpecifier,
230 ) -> StorageFuture<'a, ColdResult<Option<SealedHeader>>> {
231 Box::pin(<B as ColdStorageRead>::get_header(self, spec))
232 }
233
234 fn dyn_get_headers<'a>(
235 &'a self,
236 specs: Vec<HeaderSpecifier>,
237 ) -> StorageFuture<'a, ColdResult<Vec<Option<SealedHeader>>>> {
238 Box::pin(<B as ColdStorageRead>::get_headers(self, specs))
239 }
240
241 fn dyn_get_transaction<'a>(
242 &'a self,
243 spec: TransactionSpecifier,
244 ) -> StorageFuture<'a, ColdResult<Option<Confirmed<RecoveredTx>>>> {
245 Box::pin(<B as ColdStorageRead>::get_transaction(self, spec))
246 }
247
248 fn dyn_get_transactions_in_block<'a>(
249 &'a self,
250 block: BlockNumber,
251 ) -> StorageFuture<'a, ColdResult<Vec<RecoveredTx>>> {
252 Box::pin(<B as ColdStorageRead>::get_transactions_in_block(self, block))
253 }
254
255 fn dyn_get_transaction_count<'a>(
256 &'a self,
257 block: BlockNumber,
258 ) -> StorageFuture<'a, ColdResult<u64>> {
259 Box::pin(<B as ColdStorageRead>::get_transaction_count(self, block))
260 }
261
262 fn dyn_get_receipt<'a>(
263 &'a self,
264 spec: ReceiptSpecifier,
265 ) -> StorageFuture<'a, ColdResult<Option<ColdReceipt>>> {
266 Box::pin(<B as ColdStorageRead>::get_receipt(self, spec))
267 }
268
269 fn dyn_get_receipts_in_block<'a>(
270 &'a self,
271 block: BlockNumber,
272 ) -> StorageFuture<'a, ColdResult<Vec<ColdReceipt>>> {
273 Box::pin(<B as ColdStorageRead>::get_receipts_in_block(self, block))
274 }
275
276 fn dyn_get_signet_events<'a>(
277 &'a self,
278 spec: SignetEventsSpecifier,
279 ) -> StorageFuture<'a, ColdResult<Vec<DbSignetEvent>>> {
280 Box::pin(<B as ColdStorageRead>::get_signet_events(self, spec))
281 }
282
283 fn dyn_get_zenith_header<'a>(
284 &'a self,
285 spec: ZenithHeaderSpecifier,
286 ) -> StorageFuture<'a, ColdResult<Option<DbZenithHeader>>> {
287 Box::pin(<B as ColdStorageRead>::get_zenith_header(self, spec))
288 }
289
290 fn dyn_get_zenith_headers<'a>(
291 &'a self,
292 spec: ZenithHeaderSpecifier,
293 ) -> StorageFuture<'a, ColdResult<Vec<DbZenithHeader>>> {
294 Box::pin(<B as ColdStorageRead>::get_zenith_headers(self, spec))
295 }
296
297 fn dyn_get_latest_block<'a>(&'a self) -> StorageFuture<'a, ColdResult<Option<BlockNumber>>> {
298 Box::pin(<B as ColdStorageRead>::get_latest_block(self))
299 }
300
301 fn dyn_get_logs<'a>(
302 &'a self,
303 filter: &'a Filter,
304 max_logs: usize,
305 ) -> StorageFuture<'a, ColdResult<Vec<RpcLog>>> {
306 Box::pin(<B as ColdStorageRead>::get_logs(self, filter, max_logs))
307 }
308
309 fn dyn_produce_log_stream<'a>(
310 &'a self,
311 filter: &'a Filter,
312 params: StreamParams,
313 ) -> StorageFuture<'a, ()> {
314 Box::pin(<B as ColdStorageRead>::produce_log_stream(self, filter, params))
315 }
316
317 fn dyn_append_block<'a>(&'a self, data: BlockData) -> StorageFuture<'a, ColdResult<()>> {
318 Box::pin(<B as ColdStorageWrite>::append_block(self, data))
319 }
320
321 fn dyn_append_blocks<'a>(&'a self, data: Vec<BlockData>) -> StorageFuture<'a, ColdResult<()>> {
322 Box::pin(<B as ColdStorageWrite>::append_blocks(self, data))
323 }
324
325 fn dyn_truncate_above<'a>(&'a self, block: BlockNumber) -> StorageFuture<'a, ColdResult<()>> {
326 Box::pin(<B as ColdStorageWrite>::truncate_above(self, block))
327 }
328
329 fn dyn_drain_above<'a>(
330 &'a self,
331 block: BlockNumber,
332 ) -> StorageFuture<'a, ColdResult<Vec<Vec<ColdReceipt>>>> {
333 Box::pin(<B as ColdStorageBackend>::drain_above(self, block))
334 }
335
336 fn dyn_read_timeout(&self) -> Option<Duration> {
337 <B as ColdStorageBackend>::read_timeout(self)
338 }
339
340 fn dyn_write_timeout(&self) -> Option<Duration> {
341 <B as ColdStorageBackend>::write_timeout(self)
342 }
343}
344
345const _: fn() = || {
347 fn _assert_object_safe(_: &dyn DynColdStorageBackend) {}
348};
349
350impl ColdStorageRead for ErasedBackend {
351 fn get_header(
352 &self,
353 spec: HeaderSpecifier,
354 ) -> impl Future<Output = ColdResult<Option<SealedHeader>>> + Send {
355 self.0.dyn_get_header(spec)
356 }
357
358 fn get_headers(
359 &self,
360 specs: Vec<HeaderSpecifier>,
361 ) -> impl Future<Output = ColdResult<Vec<Option<SealedHeader>>>> + Send {
362 self.0.dyn_get_headers(specs)
363 }
364
365 fn get_transaction(
366 &self,
367 spec: TransactionSpecifier,
368 ) -> impl Future<Output = ColdResult<Option<Confirmed<RecoveredTx>>>> + Send {
369 self.0.dyn_get_transaction(spec)
370 }
371
372 fn get_transactions_in_block(
373 &self,
374 block: BlockNumber,
375 ) -> impl Future<Output = ColdResult<Vec<RecoveredTx>>> + Send {
376 self.0.dyn_get_transactions_in_block(block)
377 }
378
379 fn get_transaction_count(
380 &self,
381 block: BlockNumber,
382 ) -> impl Future<Output = ColdResult<u64>> + Send {
383 self.0.dyn_get_transaction_count(block)
384 }
385
386 fn get_receipt(
387 &self,
388 spec: ReceiptSpecifier,
389 ) -> impl Future<Output = ColdResult<Option<ColdReceipt>>> + Send {
390 self.0.dyn_get_receipt(spec)
391 }
392
393 fn get_receipts_in_block(
394 &self,
395 block: BlockNumber,
396 ) -> impl Future<Output = ColdResult<Vec<ColdReceipt>>> + Send {
397 self.0.dyn_get_receipts_in_block(block)
398 }
399
400 fn get_signet_events(
401 &self,
402 spec: SignetEventsSpecifier,
403 ) -> impl Future<Output = ColdResult<Vec<DbSignetEvent>>> + Send {
404 self.0.dyn_get_signet_events(spec)
405 }
406
407 fn get_zenith_header(
408 &self,
409 spec: ZenithHeaderSpecifier,
410 ) -> impl Future<Output = ColdResult<Option<DbZenithHeader>>> + Send {
411 self.0.dyn_get_zenith_header(spec)
412 }
413
414 fn get_zenith_headers(
415 &self,
416 spec: ZenithHeaderSpecifier,
417 ) -> impl Future<Output = ColdResult<Vec<DbZenithHeader>>> + Send {
418 self.0.dyn_get_zenith_headers(spec)
419 }
420
421 fn get_latest_block(&self) -> impl Future<Output = ColdResult<Option<BlockNumber>>> + Send {
422 self.0.dyn_get_latest_block()
423 }
424
425 fn get_logs(
426 &self,
427 filter: &Filter,
428 max_logs: usize,
429 ) -> impl Future<Output = ColdResult<Vec<RpcLog>>> + Send {
430 let this = self.clone();
431 let filter = filter.clone();
432 async move { DynColdStorageBackend::dyn_get_logs(this.0.as_ref(), &filter, max_logs).await }
437 }
438
439 fn produce_log_stream(
440 &self,
441 filter: &Filter,
442 params: StreamParams,
443 ) -> impl Future<Output = ()> + Send {
444 let this = self.clone();
445 let filter = filter.clone();
446 async move {
450 DynColdStorageBackend::dyn_produce_log_stream(this.0.as_ref(), &filter, params).await
451 }
452 }
453}
454
455impl ColdStorageWrite for ErasedBackend {
456 fn append_block(&self, data: BlockData) -> impl Future<Output = ColdResult<()>> + Send {
457 self.0.dyn_append_block(data)
458 }
459
460 fn append_blocks(&self, data: Vec<BlockData>) -> impl Future<Output = ColdResult<()>> + Send {
461 self.0.dyn_append_blocks(data)
462 }
463
464 fn truncate_above(&self, block: BlockNumber) -> impl Future<Output = ColdResult<()>> + Send {
465 self.0.dyn_truncate_above(block)
466 }
467}
468
469impl ColdStorageBackend for ErasedBackend {
470 fn read_timeout(&self) -> Option<Duration> {
471 self.0.dyn_read_timeout()
472 }
473
474 fn write_timeout(&self) -> Option<Duration> {
475 self.0.dyn_write_timeout()
476 }
477
478 fn drain_above(
479 &self,
480 block: BlockNumber,
481 ) -> impl Future<Output = ColdResult<Vec<Vec<ColdReceipt>>>> + Send {
482 self.0.dyn_drain_above(block)
483 }
484}
485
486const _: fn() = || {
489 const fn _assert_bound<B: ColdStorageBackend>() {}
490 _assert_bound::<ErasedBackend>();
491};