diff --git a/src/backend.rs b/src/backend.rs index 457e6cb..fc24743 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -68,8 +68,9 @@ type FullBlockSender = OneshotSender>>>>; type TransactionSender = OneshotSender>>; -type AddressData = Map; -type StorageData = Map; +use alloy_primitives::map::AddressHashMap; +type AddressData = AddressHashMap; +type StorageData = AddressHashMap; type BlockHashData = Map; /// Request variants that are executed by the provider @@ -935,7 +936,7 @@ mod tests { code: None, code_hash: KECCAK_EMPTY, }; - let mut account_data: AddressData = Map::new(); + let mut account_data: AddressData = Map::default(); account_data.insert(address, new_acc.clone()); backend.insert_or_update_address(account_data); @@ -999,8 +1000,8 @@ mod tests { // some rng contract from etherscan let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); - let mut storage_data: StorageData = Map::new(); - let mut storage_info: StorageInfo = Map::new(); + let mut storage_data: StorageData = Map::default(); + let mut storage_info: StorageInfo = Map::default(); storage_info.insert(U256::from(20), U256::from(10)); storage_info.insert(U256::from(30), U256::from(15)); storage_info.insert(U256::from(40), U256::from(20)); @@ -1062,7 +1063,7 @@ mod tests { // some rng contract from etherscan // let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); - let mut block_hash_data: BlockHashData = Map::new(); + let mut block_hash_data: BlockHashData = Map::default(); block_hash_data.insert(U256::from(1), B256::from(U256::from(1))); block_hash_data.insert(U256::from(2), B256::from(U256::from(2))); block_hash_data.insert(U256::from(3), B256::from(U256::from(3))); @@ -1123,8 +1124,8 @@ mod tests { // some rng contract from etherscan let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); - let mut storage_data: StorageData = Map::new(); - let mut storage_info: StorageInfo = Map::new(); + let mut storage_data: StorageData = Map::default(); + let mut storage_info: StorageInfo = Map::default(); storage_info.insert(U256::from(1), U256::from(10)); storage_info.insert(U256::from(2), U256::from(15)); storage_info.insert(U256::from(3), U256::from(20)); @@ -1143,7 +1144,7 @@ mod tests { // nullify the code new_acc.code = Some(Bytecode::new_raw(([10, 20, 30, 40]).into())); - let mut account_data: AddressData = Map::new(); + let mut account_data: AddressData = Map::default(); account_data.insert(address, new_acc.clone()); backend.insert_or_update_address(account_data); @@ -1194,8 +1195,8 @@ mod tests { let json_db = BlockchainDb::new(meta, Some(cache_path)); - let mut storage_data: StorageData = Map::new(); - let mut storage_info: StorageInfo = Map::new(); + let mut storage_data: StorageData = Map::default(); + let mut storage_info: StorageInfo = Map::default(); storage_info.insert(U256::from(1), U256::from(10)); storage_info.insert(U256::from(2), U256::from(15)); storage_info.insert(U256::from(3), U256::from(20)); diff --git a/src/cache.rs b/src/cache.rs index ad1217e..94b3d3f 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,13 +1,18 @@ //! Cache related abstraction use alloy_primitives::{Address, B256, U256}; +use alloy_provider::network::{HeaderResponse, TransactionResponse}; use parking_lot::RwLock; use revm::{ - primitives::{Account, AccountInfo, AccountStatus, HashMap as Map, KECCAK_EMPTY}, + primitives::{ + map::{AddressHashMap, HashMap}, + Account, AccountInfo, AccountStatus, BlobExcessGasAndPrice, BlockEnv, CfgEnv, + HashMap as Map, KECCAK_EMPTY, + }, DatabaseCommit, }; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use std::{ - collections::{BTreeSet, HashMap}, + collections::BTreeSet, fs, io::{BufWriter, Write}, path::{Path, PathBuf}, @@ -84,12 +89,12 @@ impl BlockchainDb { } /// Returns the map that holds the account related info - pub fn accounts(&self) -> &RwLock> { + pub fn accounts(&self) -> &RwLock> { &self.db.accounts } /// Returns the map that holds the storage related info - pub fn storage(&self) -> &RwLock> { + pub fn storage(&self) -> &RwLock> { &self.db.storage } @@ -115,10 +120,10 @@ impl BlockchainDb { } /// relevant identifying markers in the context of [BlockchainDb] -#[derive(Clone, Debug, Eq, Serialize)] +#[derive(Clone, Debug, Eq, Serialize, Default)] pub struct BlockchainDbMeta { - pub cfg_env: revm::primitives::CfgEnv, - pub block_env: revm::primitives::BlockEnv, + pub cfg_env: CfgEnv, + pub block_env: BlockEnv, /// all the hosts used to connect to pub hosts: BTreeSet, } @@ -133,6 +138,52 @@ impl BlockchainDbMeta { Self { cfg_env: env.cfg.clone(), block_env: env.block, hosts: BTreeSet::from([host]) } } + + /// Sets the chain_id in the [CfgEnv] of this instance. + /// + /// Remaining fields of [CfgEnv] are left unchanged. + pub const fn with_chain_id(mut self, chain_id: u64) -> Self { + self.cfg_env.chain_id = chain_id; + self + } + + /// Sets the [BlockEnv] of this instance using the provided [alloy_rpc_types::Block] + pub fn with_block(mut self, block: &alloy_rpc_types::Block) -> Self { + self.block_env = BlockEnv { + number: U256::from(block.header.number()), + coinbase: block.header.coinbase(), + timestamp: U256::from(block.header.timestamp()), + difficulty: U256::from(block.header.difficulty()), + basefee: block.header.base_fee_per_gas().map(U256::from).unwrap_or_default(), + gas_limit: U256::from(block.header.gas_limit()), + prevrandao: block.header.mix_hash(), + blob_excess_gas_and_price: Some(BlobExcessGasAndPrice::new( + block.header.excess_blob_gas.map(|gas| gas as u64).unwrap_or_default(), + )), + }; + + self + } + + /// Infers the host from the provided url and adds it to the set of hosts + pub fn with_url(mut self, url: &str) -> Self { + let host = Url::parse(url) + .ok() + .and_then(|url| url.host().map(|host| host.to_string())) + .unwrap_or(url.to_string()); + self.hosts.insert(host); + self + } + + /// Sets [CfgEnv] of this instance + pub fn set_cfg_env(mut self, cfg_env: revm::primitives::CfgEnv) { + self.cfg_env = cfg_env; + } + + /// Sets the [BlockEnv] of this instance + pub fn set_block_env(mut self, block_env: revm::primitives::BlockEnv) { + self.block_env = block_env; + } } // ignore hosts to not invalidate the cache when different endpoints are used, as it's commonly the @@ -248,9 +299,9 @@ impl<'de> Deserialize<'de> for BlockchainDbMeta { #[derive(Debug, Default)] pub struct MemDb { /// Account related data - pub accounts: RwLock>, + pub accounts: RwLock>, /// Storage related data - pub storage: RwLock>, + pub storage: RwLock>, /// All retrieved block hashes pub block_hashes: RwLock>, } @@ -446,8 +497,8 @@ impl<'de> Deserialize<'de> for JsonBlockCacheData { #[derive(Deserialize)] struct Data { meta: BlockchainDbMeta, - accounts: HashMap, - storage: HashMap>, + accounts: AddressHashMap, + storage: AddressHashMap>, block_hashes: HashMap, }