pub trait BlockCache:
BlockSource
+ Send
+ Sync{
// Required methods
fn get_tip_height(
&self,
range: Option<&ScanRange>,
) -> Result<Option<BlockHeight>, Self::Error>;
fn read<'life0, 'life1, 'async_trait>(
&'life0 self,
range: &'life1 ScanRange,
) -> Pin<Box<dyn Future<Output = Result<Vec<CompactBlock>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn insert<'life0, 'async_trait>(
&'life0 self,
compact_blocks: Vec<CompactBlock>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn delete<'life0, 'async_trait>(
&'life0 self,
range: ScanRange,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
// Provided method
fn truncate<'life0, 'async_trait>(
&'life0 self,
block_height: BlockHeight,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
}
Expand description
BlockCache
is a trait that extends BlockSource
and defines methods for managing
a cache of compact blocks.
§Examples
use async_trait::async_trait;
use std::sync::{Arc, Mutex};
use zcash_client_backend::data_api::{
chain::{error, BlockCache, BlockSource},
scanning::{ScanPriority, ScanRange},
};
use zcash_client_backend::proto::compact_formats::CompactBlock;
use zcash_primitives::consensus::BlockHeight;
struct ExampleBlockCache {
cached_blocks: Arc<Mutex<Vec<CompactBlock>>>,
}
#[async_trait]
impl BlockCache for ExampleBlockCache {
fn get_tip_height(&self, range: Option<&ScanRange>) -> Result<Option<BlockHeight>, Self::Error> {
let cached_blocks = self.cached_blocks.lock().unwrap();
let blocks: Vec<&CompactBlock> = match range {
Some(range) => cached_blocks
.iter()
.filter(|&block| {
let block_height = BlockHeight::from_u32(block.height as u32);
range.block_range().contains(&block_height)
})
.collect(),
None => cached_blocks.iter().collect(),
};
let highest_block = blocks.iter().max_by_key(|&&block| block.height);
Ok(highest_block.map(|&block| BlockHeight::from_u32(block.height as u32)))
}
async fn read(&self, range: &ScanRange) -> Result<Vec<CompactBlock>, Self::Error> {
Ok(self
.cached_blocks
.lock()
.unwrap()
.iter()
.filter(|block| {
let block_height = BlockHeight::from_u32(block.height as u32);
range.block_range().contains(&block_height)
})
.cloned()
.collect())
}
async fn insert(&self, mut compact_blocks: Vec<CompactBlock>) -> Result<(), Self::Error> {
self.cached_blocks
.lock()
.unwrap()
.append(&mut compact_blocks);
Ok(())
}
async fn delete(&self, range: ScanRange) -> Result<(), Self::Error> {
self.cached_blocks
.lock()
.unwrap()
.retain(|block| !range.block_range().contains(&BlockHeight::from_u32(block.height as u32)));
Ok(())
}
}
// Example usage
let rt = tokio::runtime::Runtime::new().unwrap();
let mut block_cache = ExampleBlockCache {
cached_blocks: Arc::new(Mutex::new(Vec::new())),
};
let range = ScanRange::from_parts(
BlockHeight::from_u32(1)..BlockHeight::from_u32(3),
ScanPriority::Historic,
);
let compact_blocks = vec![compact_block1, compact_block2];
// Insert blocks into the block cache
rt.block_on(async {
block_cache.insert(compact_blocks.clone()).await.unwrap();
});
assert_eq!(block_cache.cached_blocks.lock().unwrap().len(), 2);
// Find highest block in the block cache
let get_tip_height = block_cache.get_tip_height(None).unwrap();
assert_eq!(get_tip_height, Some(BlockHeight::from_u32(2)));
// Read from the block cache
rt.block_on(async {
let blocks_from_cache = block_cache.read(&range).await.unwrap();
assert_eq!(blocks_from_cache, compact_blocks);
});
// Truncate the block cache
rt.block_on(async {
block_cache.truncate(BlockHeight::from_u32(1)).await.unwrap();
});
assert_eq!(block_cache.cached_blocks.lock().unwrap().len(), 1);
assert_eq!(
block_cache.get_tip_height(None).unwrap(),
Some(BlockHeight::from_u32(1))
);
// Delete blocks from the block cache
rt.block_on(async {
block_cache.delete(range).await.unwrap();
});
assert_eq!(block_cache.cached_blocks.lock().unwrap().len(), 0);
assert_eq!(block_cache.get_tip_height(None).unwrap(), None);
Required Methods§
Sourcefn get_tip_height(
&self,
range: Option<&ScanRange>,
) -> Result<Option<BlockHeight>, Self::Error>
fn get_tip_height( &self, range: Option<&ScanRange>, ) -> Result<Option<BlockHeight>, Self::Error>
Finds the height of the highest block known to the block cache within a specified range.
If range
is None
, returns the tip of the entire cache.
If no blocks are found in the cache, returns Ok(None
).
Sourcefn read<'life0, 'life1, 'async_trait>(
&'life0 self,
range: &'life1 ScanRange,
) -> Pin<Box<dyn Future<Output = Result<Vec<CompactBlock>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read<'life0, 'life1, 'async_trait>(
&'life0 self,
range: &'life1 ScanRange,
) -> Pin<Box<dyn Future<Output = Result<Vec<CompactBlock>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Retrieves contiguous compact blocks specified by the given range
from the block cache.
Short reads are allowed, meaning that this method may return fewer blocks than requested
provided that all returned blocks are contiguous and start from range.block_range().start
.
§Errors
This method should return an error if contiguous blocks cannot be read from the cache, indicating there are blocks missing.
Sourcefn insert<'life0, 'async_trait>(
&'life0 self,
compact_blocks: Vec<CompactBlock>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn insert<'life0, 'async_trait>(
&'life0 self,
compact_blocks: Vec<CompactBlock>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Inserts a vec of compact blocks into the block cache.
This method permits insertion of non-contiguous compact blocks.
Sourcefn delete<'life0, 'async_trait>(
&'life0 self,
range: ScanRange,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn delete<'life0, 'async_trait>(
&'life0 self,
range: ScanRange,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Deletes a range of compact blocks from the block cache.
§Errors
In the case of an error, some blocks requested for deletion may remain in the block cache.
Provided Methods§
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.