use crate::{
ColdReceipt, ColdResult, Confirmed, Filter, HeaderSpecifier, ReceiptSpecifier, RpcLog,
SignetEventsSpecifier, StreamParams, TransactionSpecifier, ZenithHeaderSpecifier,
};
use alloy::primitives::BlockNumber;
use signet_storage_types::{
DbSignetEvent, DbZenithHeader, ExecutedBlock, Receipt, RecoveredTx, SealedHeader,
};
use std::future::Future;
use tokio_stream::wrappers::ReceiverStream;
pub type LogStream = ReceiverStream<ColdResult<RpcLog>>;
#[derive(Debug, Clone)]
pub struct BlockData {
pub header: SealedHeader,
pub transactions: Vec<RecoveredTx>,
pub receipts: Vec<Receipt>,
pub signet_events: Vec<DbSignetEvent>,
pub zenith_header: Option<DbZenithHeader>,
}
impl BlockData {
pub const fn new(
header: SealedHeader,
transactions: Vec<RecoveredTx>,
receipts: Vec<Receipt>,
signet_events: Vec<DbSignetEvent>,
zenith_header: Option<DbZenithHeader>,
) -> Self {
Self { header, transactions, receipts, signet_events, zenith_header }
}
pub fn block_number(&self) -> BlockNumber {
self.header.number
}
}
impl From<ExecutedBlock> for BlockData {
fn from(block: ExecutedBlock) -> Self {
Self::new(
block.header,
block.transactions,
block.receipts,
block.signet_events,
block.zenith_header,
)
}
}
pub trait ColdStorageRead: Clone + Send + Sync + 'static {
fn get_header(
&self,
spec: HeaderSpecifier,
) -> impl Future<Output = ColdResult<Option<SealedHeader>>> + Send;
fn get_headers(
&self,
specs: Vec<HeaderSpecifier>,
) -> impl Future<Output = ColdResult<Vec<Option<SealedHeader>>>> + Send;
fn get_transaction(
&self,
spec: TransactionSpecifier,
) -> impl Future<Output = ColdResult<Option<Confirmed<RecoveredTx>>>> + Send;
fn get_transactions_in_block(
&self,
block: BlockNumber,
) -> impl Future<Output = ColdResult<Vec<RecoveredTx>>> + Send;
fn get_transaction_count(
&self,
block: BlockNumber,
) -> impl Future<Output = ColdResult<u64>> + Send;
fn get_receipt(
&self,
spec: ReceiptSpecifier,
) -> impl Future<Output = ColdResult<Option<ColdReceipt>>> + Send;
fn get_receipts_in_block(
&self,
block: BlockNumber,
) -> impl Future<Output = ColdResult<Vec<ColdReceipt>>> + Send;
fn get_signet_events(
&self,
spec: SignetEventsSpecifier,
) -> impl Future<Output = ColdResult<Vec<DbSignetEvent>>> + Send;
fn get_zenith_header(
&self,
spec: ZenithHeaderSpecifier,
) -> impl Future<Output = ColdResult<Option<DbZenithHeader>>> + Send;
fn get_zenith_headers(
&self,
spec: ZenithHeaderSpecifier,
) -> impl Future<Output = ColdResult<Vec<DbZenithHeader>>> + Send;
fn get_latest_block(&self) -> impl Future<Output = ColdResult<Option<BlockNumber>>> + Send;
fn get_logs(
&self,
filter: &Filter,
max_logs: usize,
) -> impl Future<Output = ColdResult<Vec<RpcLog>>> + Send;
fn produce_log_stream(
&self,
filter: &Filter,
params: StreamParams,
) -> impl Future<Output = ()> + Send;
}
pub trait ColdStorageWrite: Send + 'static {
fn append_block(&mut self, data: BlockData) -> impl Future<Output = ColdResult<()>> + Send;
fn append_blocks(
&mut self,
data: Vec<BlockData>,
) -> impl Future<Output = ColdResult<()>> + Send;
fn truncate_above(&mut self, block: BlockNumber)
-> impl Future<Output = ColdResult<()>> + Send;
}
pub trait ColdStorage: ColdStorageRead + ColdStorageWrite {
fn drain_above(
&mut self,
block: BlockNumber,
) -> impl Future<Output = ColdResult<Vec<Vec<ColdReceipt>>>> + Send {
async move {
let mut all_receipts = Vec::new();
if let Some(latest) = self.get_latest_block().await? {
for n in (block + 1)..=latest {
all_receipts.push(self.get_receipts_in_block(n).await?);
}
}
self.truncate_above(block).await?;
Ok(all_receipts)
}
}
}