diff --git a/crates/cold/src/task/handle.rs b/crates/cold/src/task/handle.rs index be49132..fa9099f 100644 --- a/crates/cold/src/task/handle.rs +++ b/crates/cold/src/task/handle.rs @@ -331,8 +331,8 @@ impl ColdStorageReadHandle { /// /// # Read Access /// -/// All read methods from [`ColdStorageReadHandle`] are available on this -/// handle via [`Deref`](std::ops::Deref). +/// All read methods from [`ColdStorageReadHandle`] are also available +/// directly on this handle. /// /// # Usage /// @@ -356,14 +356,6 @@ pub struct ColdStorageHandle { write_sender: mpsc::Sender, } -impl std::ops::Deref for ColdStorageHandle { - type Target = ColdStorageReadHandle; - - fn deref(&self) -> &Self::Target { - &self.reader - } -} - impl ColdStorageHandle { /// Create a new handle with the given senders. pub(crate) const fn new( @@ -463,4 +455,182 @@ impl ColdStorageHandle { .try_send(ColdWriteRequest::TruncateAbove { block, resp }) .map_err(map_dispatch_error) } + + // ========================================================================== + // Read Operations (delegated to ColdStorageReadHandle) + // ========================================================================== + + /// Get a header by specifier. + pub async fn get_header(&self, spec: HeaderSpecifier) -> ColdResult> { + self.reader.get_header(spec).await + } + + /// Get a header by block number. + pub async fn get_header_by_number( + &self, + block: BlockNumber, + ) -> ColdResult> { + self.reader.get_header_by_number(block).await + } + + /// Get a header by block hash. + pub async fn get_header_by_hash(&self, hash: B256) -> ColdResult> { + self.reader.get_header_by_hash(hash).await + } + + /// Get multiple headers by specifiers. + pub async fn get_headers( + &self, + specs: Vec, + ) -> ColdResult>> { + self.reader.get_headers(specs).await + } + + /// Get a transaction by specifier, with block confirmation metadata. + pub async fn get_transaction( + &self, + spec: TransactionSpecifier, + ) -> ColdResult>> { + self.reader.get_transaction(spec).await + } + + /// Get a transaction by hash. + pub async fn get_tx_by_hash(&self, hash: B256) -> ColdResult>> { + self.reader.get_tx_by_hash(hash).await + } + + /// Get a transaction by block number and index. + pub async fn get_tx_by_block_and_index( + &self, + block: BlockNumber, + index: u64, + ) -> ColdResult>> { + self.reader.get_tx_by_block_and_index(block, index).await + } + + /// Get a transaction by block hash and index. + pub async fn get_tx_by_block_hash_and_index( + &self, + block_hash: B256, + index: u64, + ) -> ColdResult>> { + self.reader.get_tx_by_block_hash_and_index(block_hash, index).await + } + + /// Get all transactions in a block. + pub async fn get_transactions_in_block( + &self, + block: BlockNumber, + ) -> ColdResult> { + self.reader.get_transactions_in_block(block).await + } + + /// Get the transaction count for a block. + pub async fn get_transaction_count(&self, block: BlockNumber) -> ColdResult { + self.reader.get_transaction_count(block).await + } + + /// Get a receipt by specifier. + pub async fn get_receipt(&self, spec: ReceiptSpecifier) -> ColdResult> { + self.reader.get_receipt(spec).await + } + + /// Get a receipt by transaction hash. + pub async fn get_receipt_by_tx_hash(&self, hash: B256) -> ColdResult> { + self.reader.get_receipt_by_tx_hash(hash).await + } + + /// Get a receipt by block number and index. + pub async fn get_receipt_by_block_and_index( + &self, + block: BlockNumber, + index: u64, + ) -> ColdResult> { + self.reader.get_receipt_by_block_and_index(block, index).await + } + + /// Get all receipts in a block. + pub async fn get_receipts_in_block(&self, block: BlockNumber) -> ColdResult> { + self.reader.get_receipts_in_block(block).await + } + + /// Get signet events by specifier. + pub async fn get_signet_events( + &self, + spec: SignetEventsSpecifier, + ) -> ColdResult> { + self.reader.get_signet_events(spec).await + } + + /// Get signet events in a block. + pub async fn get_signet_events_in_block( + &self, + block: BlockNumber, + ) -> ColdResult> { + self.reader.get_signet_events_in_block(block).await + } + + /// Get signet events in a range of blocks. + pub async fn get_signet_events_in_range( + &self, + start: BlockNumber, + end: BlockNumber, + ) -> ColdResult> { + self.reader.get_signet_events_in_range(start, end).await + } + + /// Get a zenith header by block number. + pub async fn get_zenith_header( + &self, + block: BlockNumber, + ) -> ColdResult> { + self.reader.get_zenith_header(block).await + } + + /// Get zenith headers by specifier. + pub async fn get_zenith_headers( + &self, + spec: ZenithHeaderSpecifier, + ) -> ColdResult> { + self.reader.get_zenith_headers(spec).await + } + + /// Get zenith headers in a range of blocks. + pub async fn get_zenith_headers_in_range( + &self, + start: BlockNumber, + end: BlockNumber, + ) -> ColdResult> { + self.reader.get_zenith_headers_in_range(start, end).await + } + + /// Filter logs by block range, address, and topics. + /// + /// Follows `eth_getLogs` semantics. Returns matching logs ordered by + /// `(block_number, tx_index, log_index)`. + /// + /// # Errors + /// + /// Returns [`ColdStorageError::TooManyLogs`] if the query would produce + /// more than `max_logs` results. + pub async fn get_logs(&self, filter: Filter, max_logs: usize) -> ColdResult> { + self.reader.get_logs(filter, max_logs).await + } + + /// Stream logs matching a filter. + /// + /// See [`ColdStorageReadHandle::stream_logs`] for full documentation. + pub async fn stream_logs( + &self, + filter: Filter, + max_logs: usize, + deadline: Duration, + ) -> ColdResult { + self.reader.stream_logs(filter, max_logs, deadline).await + } + + /// Get the latest block number in storage. + pub async fn get_latest_block(&self) -> ColdResult> { + self.reader.get_latest_block().await + } } diff --git a/crates/hot-mdbx/src/cursor.rs b/crates/hot-mdbx/src/cursor.rs index 4157406..3f806ed 100644 --- a/crates/hot-mdbx/src/cursor.rs +++ b/crates/hot-mdbx/src/cursor.rs @@ -9,10 +9,7 @@ use signet_hot::{ }, }; use signet_libmdbx::{DupItem, Ro, Rw, RwSync, TransactionKind, tx::WriteMarker, tx::iter}; -use std::{ - borrow::Cow, - ops::{Deref, DerefMut}, -}; +use std::borrow::Cow; /// Read only Cursor. pub type CursorRo<'a> = Cursor<'a, Ro>; @@ -50,20 +47,6 @@ impl std::fmt::Debug for Cursor<'_, K> { } } -impl<'a, K: TransactionKind> Deref for Cursor<'a, K> { - type Target = signet_libmdbx::Cursor<'a, K>; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl<'a, K: TransactionKind> DerefMut for Cursor<'a, K> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner - } -} - impl<'a, K: TransactionKind> Cursor<'a, K> { /// Creates a new `Cursor` wrapping the given `libmdbx` cursor. pub const fn new(inner: signet_libmdbx::Cursor<'a, K>, fsi: FixedSizeInfo) -> Self { diff --git a/crates/hot-mdbx/src/lib.rs b/crates/hot-mdbx/src/lib.rs index d0cc255..3639b02 100644 --- a/crates/hot-mdbx/src/lib.rs +++ b/crates/hot-mdbx/src/lib.rs @@ -56,12 +56,7 @@ use signet_libmdbx::{ Environment, EnvironmentFlags, Geometry, Mode, Ro, RoSync, Rw, RwSync, SyncMode, ffi, sys::{HandleSlowReadersReturnCode, PageSize}, }; -use std::{ - collections::HashMap, - ops::{Deref, Range}, - path::Path, - sync::Arc, -}; +use std::{collections::HashMap, ops::Range, path::Path, sync::Arc}; mod cursor; pub use cursor::{Cursor, CursorRo, CursorRoSync, CursorRw, CursorRwSync}; @@ -410,14 +405,6 @@ impl DatabaseEnv { } } -impl Deref for DatabaseEnv { - type Target = Environment; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - impl HotKv for DatabaseEnv { type RoTx = Tx; type RwTx = Tx; diff --git a/crates/types/src/int_list.rs b/crates/types/src/int_list.rs index d8617fc..e931538 100644 --- a/crates/types/src/int_list.rs +++ b/crates/types/src/int_list.rs @@ -35,14 +35,6 @@ pub enum IntegerListError { #[derive(Clone, PartialEq, Default)] pub struct IntegerList(RoaringTreemap); -impl core::ops::Deref for IntegerList { - type Target = RoaringTreemap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - impl fmt::Debug for IntegerList { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("IntegerList")?; @@ -123,4 +115,54 @@ impl IntegerList { .map(Self) .map_err(|_| IntegerListError::FailedToDeserialize) } + + /// Returns an iterator over the integers in the list. + pub fn iter(&self) -> roaring::treemap::Iter<'_> { + self.0.iter() + } + + /// Returns the number of integers in the list. + pub fn len(&self) -> u64 { + self.0.len() + } + + /// Returns `true` if the list contains no integers. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Returns `true` if the list contains the given value. + pub fn contains(&self, value: u64) -> bool { + self.0.contains(value) + } + + /// Returns the smallest value in the list, or `None` if empty. + pub fn min(&self) -> Option { + self.0.min() + } + + /// Returns the largest value in the list, or `None` if empty. + pub fn max(&self) -> Option { + self.0.max() + } + + /// Returns the number of integers that are `<= value`. + pub fn rank(&self, value: u64) -> u64 { + self.0.rank(value) + } + + /// Returns the `n`th integer in the list (0-indexed). + pub fn select(&self, n: u64) -> Option { + self.0.select(n) + } + + /// Returns the serialized size of the list in bytes. + pub fn serialized_size(&self) -> usize { + self.0.serialized_size() + } + + /// Serializes the list into the given writer. + pub fn serialize_into(&self, writer: W) -> std::io::Result<()> { + self.0.serialize_into(writer) + } }