use cached::{Cached, SizedCache};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg(test)]
pub struct SignatureCacheStatistics {
pub size: usize,
pub hits: u64,
pub misses: u64,
}
#[cfg(test)]
impl SignatureCacheStatistics {
pub(super) fn new(size: usize, hits: u64, misses: u64) -> Self {
Self { size, hits, misses }
}
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub(crate) struct SignatureCacheEntry {
hash: [u8; 32],
}
impl SignatureCacheEntry {
pub(crate) fn new(pk: &[u8], sig: &[u8], msg: &[u8]) -> Self {
use sha2::{Digest, Sha256};
let mut sha256 = Sha256::new();
sha256.update(pk);
sha256.update(sig);
sha256.update(msg);
let hash = sha256.finalize().into();
Self { hash }
}
}
pub(crate) struct SignatureCache {
cache: parking_lot::Mutex<SizedCache<SignatureCacheEntry, ()>>,
}
lazy_static::lazy_static! {
static ref GLOBAL_SIGNATURE_CACHE: SignatureCache = SignatureCache::new(SignatureCache::SIZE_OF_GLOBAL_CACHE);
}
impl SignatureCache {
pub const SIZE_OF_GLOBAL_CACHE: usize = 100000;
pub(super) fn new(max_size: usize) -> Self {
let cache = parking_lot::Mutex::<SizedCache<SignatureCacheEntry, ()>>::new(
SizedCache::with_size(max_size),
);
Self { cache }
}
pub(crate) fn global() -> &'static Self {
&GLOBAL_SIGNATURE_CACHE
}
pub(crate) fn contains(&self, entry: &SignatureCacheEntry) -> bool {
let mut cache = self.cache.lock();
cache.cache_get(entry).is_some()
}
pub(crate) fn insert(&self, entry: &SignatureCacheEntry) {
let mut cache = self.cache.lock();
cache.cache_set(*entry, ());
}
#[cfg(test)]
pub(crate) fn cache_statistics(&self) -> SignatureCacheStatistics {
let cache = self.cache.lock();
let cache_size = cache.cache_size();
let hits = cache.cache_hits().unwrap_or(0);
let misses = cache.cache_misses().unwrap_or(0);
SignatureCacheStatistics::new(cache_size, hits, misses)
}
}