use std::collections::HashMap;
use std::path::{Path, PathBuf};
use alloy_primitives::{Address, U256};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use super::versioned;
use crate::errors::PersistenceError;
const IMMUTABLE_CACHE_MAGIC: &[u8; 8] = b"EFCMETA\0";
const IMMUTABLE_CACHE_VERSION: u32 = 2;
#[derive(Debug, Clone)]
pub struct CacheConfig {
pub cache_dir: PathBuf,
pub chain_id: u64,
pub maintain_addresses: HashSet<Address>,
pub maintain_slots: HashMap<Address, HashSet<U256>>,
}
impl CacheConfig {
pub fn new(
cache_dir: impl Into<PathBuf>,
chain_id: u64,
maintain_addresses: HashSet<Address>,
maintain_slots: HashMap<Address, HashSet<U256>>,
) -> Self {
Self {
cache_dir: cache_dir.into(),
chain_id,
maintain_addresses,
maintain_slots,
}
}
pub(crate) fn chain_dir(&self) -> PathBuf {
self.cache_dir.join(format!("chain_{}", self.chain_id))
}
pub(crate) fn bytecode_cache_path(&self) -> PathBuf {
self.chain_dir().join("bytecodes.bin")
}
pub(crate) fn immutable_cache_path(&self) -> PathBuf {
self.chain_dir().join("immutable_data.bin")
}
pub(crate) fn code_seeds_cache_path(&self) -> PathBuf {
self.chain_dir().join("code_seeds.bin")
}
pub fn binary_state_cache_path(&self) -> PathBuf {
self.chain_dir().join("evm_state.bin")
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ImmutableDataCache {
pub token_decimals: HashMap<Address, u8>,
}
impl ImmutableDataCache {
pub fn load(path: &Path) -> Option<Self> {
let data = std::fs::read(path).ok()?;
versioned::decode(
&data,
IMMUTABLE_CACHE_MAGIC,
IMMUTABLE_CACHE_VERSION,
"immutable data cache",
)
}
pub fn save(&self, path: &Path) -> Result<(), PersistenceError> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.map_err(|err| PersistenceError::create_dir(parent, err))?;
}
let data = versioned::encode(
IMMUTABLE_CACHE_MAGIC,
IMMUTABLE_CACHE_VERSION,
self,
"immutable data cache",
)?;
std::fs::write(path, data).map_err(|err| PersistenceError::write(path, err))?;
Ok(())
}
pub fn get_token_decimals(&self, token: Address) -> Option<u8> {
self.token_decimals.get(&token).copied()
}
pub fn set_token_decimals(&mut self, token: Address, decimals: u8) {
self.token_decimals.insert(token, decimals);
}
pub fn is_empty(&self) -> bool {
self.token_decimals.is_empty()
}
pub fn len(&self) -> usize {
self.token_decimals.len()
}
}