anvil_zksync_common/
cache.rs

1use super::{sh_err, sh_warn};
2use clap::ValueEnum;
3use rustc_hash::FxHashMap;
4use serde::{Deserialize, Serialize};
5use std::fs;
6use std::fs::File;
7use std::io::{BufReader, BufWriter};
8use std::path::Path;
9use std::result::Result;
10use std::str::FromStr;
11use zksync_types::H256;
12use zksync_types::Transaction as RawTransaction;
13use zksync_types::api::{Block, BridgeAddresses, Transaction, TransactionVariant};
14
15pub const DEFAULT_DISK_CACHE_DIR: &str = ".cache";
16/// Caches full blocks by their hashes
17const CACHE_TYPE_BLOCKS_FULL: &str = "blocks_full";
18/// Caches minimal blocks by their hashes
19const CACHE_TYPE_BLOCKS_MIN: &str = "blocks_min";
20/// Caches raw transactions by their hashes
21const CACHE_TYPE_BLOCK_RAW_TRANSACTIONS: &str = "block_raw_transactions";
22/// Caches transactions by their hashes
23const CACHE_TYPE_TRANSACTIONS: &str = "transactions";
24/// Caching resolver functions by their selectors
25const CACHE_TYPE_RESOLVER_SELECTORS: &str = "resolver_selectors";
26/// Caches arbitrary values by their keys
27const CACHE_TYPE_KEY_VALUE: &str = "key_value";
28
29/// Caching key for bridge addresses
30const CACHE_KEY_BRIDGE_ADDRESSES: &str = "bridge_addresses";
31
32/// Cache type for the node.
33#[derive(ValueEnum, Deserialize, Default, Debug, Copy, Clone)]
34pub enum CacheType {
35    None,
36    Memory,
37    #[default]
38    Disk,
39}
40
41/// Cache configuration options.
42#[derive(Deserialize, Debug, Clone)]
43pub enum CacheConfig {
44    #[serde(rename = "none")]
45    None,
46    #[serde(rename = "memory")]
47    Memory,
48    #[serde(rename = "disk")]
49    Disk { dir: String, reset: bool },
50}
51
52impl Default for CacheConfig {
53    fn default() -> Self {
54        Self::Disk {
55            dir: String::from(DEFAULT_DISK_CACHE_DIR),
56            reset: false,
57        }
58    }
59}
60
61/// A general purpose cache.
62#[derive(Default, Debug, Clone)]
63pub struct Cache {
64    config: CacheConfig,
65    block_hashes: FxHashMap<u64, H256>,
66    blocks_full: FxHashMap<H256, Block<TransactionVariant>>,
67    blocks_min: FxHashMap<H256, Block<TransactionVariant>>,
68    block_raw_transactions: FxHashMap<u64, Vec<RawTransaction>>,
69    transactions: FxHashMap<H256, Transaction>,
70    resolver_selectors: FxHashMap<String, String>,
71    bridge_addresses: Option<BridgeAddresses>,
72    confirmed_tokens: FxHashMap<(u32, u8), Vec<zksync_web3_decl::types::Token>>,
73}
74
75impl Cache {
76    /// Creates a new cache with the provided config.
77    pub fn new(config: CacheConfig) -> Self {
78        let mut cache = Cache {
79            config: config.clone(),
80            ..Default::default()
81        };
82
83        if let CacheConfig::Disk { dir, reset } = &config {
84            if *reset {
85                for cache_type in [
86                    CACHE_TYPE_BLOCKS_FULL,
87                    CACHE_TYPE_BLOCKS_MIN,
88                    CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
89                    CACHE_TYPE_TRANSACTIONS,
90                    CACHE_TYPE_RESOLVER_SELECTORS,
91                    CACHE_TYPE_KEY_VALUE,
92                ] {
93                    fs::remove_dir_all(Path::new(dir).join(cache_type)).unwrap_or_else(|err| {
94                        sh_warn!(
95                            "failed removing directory {:?}: {:?}",
96                            Path::new(dir).join(cache_type),
97                            err
98                        )
99                    });
100                }
101
102                fs::remove_dir(Path::new(dir))
103                    .unwrap_or_else(|err| sh_warn!("failed removing cache directory: {:?}", err));
104            }
105
106            for cache_type in [
107                CACHE_TYPE_BLOCKS_FULL,
108                CACHE_TYPE_BLOCKS_MIN,
109                CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
110                CACHE_TYPE_TRANSACTIONS,
111                CACHE_TYPE_RESOLVER_SELECTORS,
112                CACHE_TYPE_KEY_VALUE,
113            ] {
114                fs::create_dir_all(Path::new(dir).join(cache_type)).unwrap_or_else(|err| {
115                    panic!("failed creating directory {cache_type}: {err:?}");
116                });
117            }
118            cache
119                .read_all_from_disk(dir)
120                .unwrap_or_else(|err| sh_err!("failed reading cache from disk: {:?}", err));
121        }
122
123        cache
124    }
125
126    /// Returns the cached full/minimal block for the provided hash.
127    pub fn get_block(
128        &self,
129        hash: &H256,
130        full_transactions: bool,
131    ) -> Option<&Block<TransactionVariant>> {
132        if matches!(self.config, CacheConfig::None) {
133            return None;
134        }
135
136        if full_transactions {
137            self.blocks_full.get(hash)
138        } else {
139            self.blocks_min.get(hash)
140        }
141    }
142
143    /// Cache a full/minimal block for the provided hash.
144    pub fn insert_block(
145        &mut self,
146        hash: H256,
147        full_transactions: bool,
148        block: Block<TransactionVariant>,
149    ) {
150        if matches!(self.config, CacheConfig::None) {
151            return;
152        }
153
154        self.block_hashes.insert(block.number.as_u64(), block.hash);
155        if full_transactions {
156            self.write_to_disk(CACHE_TYPE_BLOCKS_FULL, format!("{hash:#x}"), &block);
157            self.blocks_full.insert(hash, block);
158        } else {
159            self.write_to_disk(CACHE_TYPE_BLOCKS_MIN, format!("{hash:#x}"), &block);
160            self.blocks_min.insert(hash, block);
161        }
162    }
163
164    /// Returns the cached full/minimal block for the provided hash.
165    pub fn get_block_hash(&self, number: &u64) -> Option<&H256> {
166        if matches!(self.config, CacheConfig::None) {
167            return None;
168        }
169
170        self.block_hashes.get(number)
171    }
172
173    /// Returns the cached raw transactions for the provided block number.
174    pub fn get_block_raw_transactions(&self, number: &u64) -> Option<&Vec<RawTransaction>> {
175        if matches!(self.config, CacheConfig::None) {
176            return None;
177        }
178
179        self.block_raw_transactions.get(number)
180    }
181
182    /// Cache confirmed tokens
183    pub fn set_confirmed_tokens(
184        &mut self,
185        from: u32,
186        limit: u8,
187        confirmed_tokens: Vec<zksync_web3_decl::types::Token>,
188    ) {
189        if matches!(self.config, CacheConfig::None) {
190            return;
191        }
192        self.confirmed_tokens
193            .insert((from, limit), confirmed_tokens);
194    }
195
196    /// Cache the raw transactions for the provided block number.
197    pub fn insert_block_raw_transactions(
198        &mut self,
199        number: u64,
200        transactions: Vec<RawTransaction>,
201    ) {
202        if matches!(self.config, CacheConfig::None) {
203            return;
204        }
205
206        self.write_to_disk(
207            CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
208            format!("{number}"),
209            &transactions,
210        );
211        self.block_raw_transactions.insert(number, transactions);
212    }
213
214    /// Returns the cached transaction for the provided hash.
215    pub fn get_transaction(&self, hash: &H256) -> Option<&Transaction> {
216        if matches!(self.config, CacheConfig::None) {
217            return None;
218        }
219
220        self.transactions.get(hash)
221    }
222
223    /// Returns the cached resolved function/event selector for the provided selector.
224    pub fn get_resolver_selector(&self, selector: &String) -> Option<&String> {
225        if matches!(self.config, CacheConfig::None) {
226            return None;
227        }
228
229        self.resolver_selectors.get(selector)
230    }
231
232    /// Cache a transaction for the provided hash.
233    pub fn insert_transaction(&mut self, hash: H256, transaction: Transaction) {
234        if matches!(self.config, CacheConfig::None) {
235            return;
236        }
237
238        self.write_to_disk(CACHE_TYPE_TRANSACTIONS, format!("{hash:#x}"), &transaction);
239        self.transactions.insert(hash, transaction);
240    }
241
242    /// Cache a resolver function for the provided selector.
243    pub fn insert_resolver_selector(&mut self, selector: String, selector_value: String) {
244        if matches!(self.config, CacheConfig::None) {
245            return;
246        }
247
248        self.write_to_disk(
249            CACHE_TYPE_RESOLVER_SELECTORS,
250            selector.clone(),
251            &selector_value,
252        );
253        self.resolver_selectors.insert(selector, selector_value);
254    }
255
256    /// Returns the cached bridge addresses for the provided hash.
257    pub fn get_bridge_addresses(&self) -> Option<&BridgeAddresses> {
258        if matches!(self.config, CacheConfig::None) {
259            return None;
260        }
261
262        self.bridge_addresses.as_ref()
263    }
264
265    /// Cache default bridge addresses.
266    pub fn set_bridge_addresses(&mut self, bridge_addresses: BridgeAddresses) {
267        if matches!(self.config, CacheConfig::None) {
268            return;
269        }
270
271        self.write_to_disk(
272            CACHE_TYPE_KEY_VALUE,
273            String::from(CACHE_KEY_BRIDGE_ADDRESSES),
274            &bridge_addresses,
275        );
276        self.bridge_addresses = Some(bridge_addresses);
277    }
278
279    /// Reads the cache contents from the disk, if available.
280    fn read_all_from_disk(&mut self, dir: &str) -> Result<(), String> {
281        for cache_type in [
282            CACHE_TYPE_BLOCKS_FULL,
283            CACHE_TYPE_BLOCKS_MIN,
284            CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
285            CACHE_TYPE_TRANSACTIONS,
286            CACHE_TYPE_RESOLVER_SELECTORS,
287            CACHE_TYPE_KEY_VALUE,
288        ] {
289            let cache_dir = Path::new(dir).join(cache_type);
290            let dir_listing = fs::read_dir(cache_dir.clone())
291                .map_err(|err| format!("failed reading dir '{cache_dir:?}': {err:?}"))?
292                .flatten();
293            for file in dir_listing {
294                let key = file
295                    .file_name()
296                    .to_str()
297                    .ok_or_else(|| String::from("failed converting filename to string"))?
298                    .to_string();
299
300                let cache_file = File::open(file.path()).map_err(|err| {
301                    format!("failed reading file: '{:?}': {:?}", file.path(), err)
302                })?;
303                let reader = BufReader::new(cache_file);
304                match cache_type {
305                    CACHE_TYPE_BLOCKS_FULL => {
306                        let key = H256::from_str(&key).map_err(|err| {
307                            format!("invalid key for cache file '{key:?}': {err:?}")
308                        })?;
309                        let block: Block<TransactionVariant> = serde_json::from_reader(reader)
310                            .map_err(|err| {
311                                format!("failed parsing json for cache file '{key:?}': {err:?}")
312                            })?;
313                        self.block_hashes.insert(block.number.as_u64(), block.hash);
314                        self.blocks_full.insert(key, block);
315                    }
316                    CACHE_TYPE_BLOCKS_MIN => {
317                        let key = H256::from_str(&key).map_err(|err| {
318                            format!("invalid key for cache file '{key:?}': {err:?}")
319                        })?;
320                        let block: Block<TransactionVariant> = serde_json::from_reader(reader)
321                            .map_err(|err| {
322                                format!("failed parsing json for cache file '{key:?}': {err:?}")
323                            })?;
324                        self.block_hashes.insert(block.number.as_u64(), block.hash);
325                        self.blocks_min.insert(key, block);
326                    }
327                    CACHE_TYPE_BLOCK_RAW_TRANSACTIONS => {
328                        let key = key.parse::<u64>().map_err(|err| {
329                            format!("invalid key for cache file '{key:?}': {err:?}")
330                        })?;
331                        let transactions: Vec<RawTransaction> = serde_json::from_reader(reader)
332                            .map_err(|err| {
333                                format!("failed parsing json for cache file '{key:?}': {err:?}")
334                            })?;
335                        self.block_raw_transactions.insert(key, transactions);
336                    }
337                    CACHE_TYPE_TRANSACTIONS => {
338                        let key = H256::from_str(&key).map_err(|err| {
339                            format!("invalid key for cache file '{key:?}': {err:?}")
340                        })?;
341                        let transaction: Transaction =
342                            serde_json::from_reader(reader).map_err(|err| {
343                                format!("failed parsing json for cache file '{key:?}': {err:?}")
344                            })?;
345                        self.transactions.insert(key, transaction);
346                    }
347                    CACHE_TYPE_RESOLVER_SELECTORS => {
348                        let selector: String = serde_json::from_reader(reader).map_err(|err| {
349                            format!("failed parsing json for cache file '{key:?}': {err:?}")
350                        })?;
351                        self.resolver_selectors.insert(key, selector);
352                    }
353                    CACHE_TYPE_KEY_VALUE => match key.as_str() {
354                        CACHE_KEY_BRIDGE_ADDRESSES => {
355                            self.bridge_addresses =
356                                Some(serde_json::from_reader(reader).map_err(|err| {
357                                    format!("failed parsing json for cache file '{key:?}': {err:?}")
358                                })?);
359                        }
360                        _ => return Err(format!("invalid cache_type_value key {cache_type}")),
361                    },
362                    _ => return Err(format!("invalid cache_type {cache_type}")),
363                }
364            }
365        }
366
367        Ok(())
368    }
369
370    /// Writes the cache contents to disk, if supported.
371    fn write_to_disk<T: Serialize>(&self, cache_type: &'static str, key: String, data: &T) {
372        if let CacheConfig::Disk { dir, .. } = &self.config {
373            let file = Path::new(&dir).join(cache_type).join(key);
374
375            tracing::debug!("writing cache {:?}", file);
376            match File::create(file.clone()) {
377                Ok(cache_file) => {
378                    let writer = BufWriter::new(cache_file);
379                    if let Err(err) = serde_json::to_writer(writer, data) {
380                        sh_err!("failed writing to cache '{:?}': {:?}", file, err);
381                    }
382                }
383                Err(err) => sh_err!("failed creating file: '{:?}': {:?}", file, err),
384            }
385        }
386    }
387}
388
389#[cfg(test)]
390mod tests {
391    use zksync_types::{Execute, ExecuteTransactionCommon};
392    use zksync_types::{H160, U64};
393
394    // use crate::testing;
395
396    use super::*;
397
398    #[test]
399    fn test_cache_config_none_disables_cache() {
400        let mut cache = Cache::new(CacheConfig::None);
401
402        cache.insert_block(H256::zero(), true, Default::default());
403        assert_eq!(None, cache.get_block(&H256::zero(), true));
404        assert_eq!(None, cache.get_block_hash(&0));
405
406        cache.insert_block(H256::zero(), false, Default::default());
407        assert_eq!(None, cache.get_block(&H256::zero(), false));
408        assert_eq!(None, cache.get_block_hash(&0));
409
410        cache.insert_block_raw_transactions(0, Default::default());
411        assert_eq!(None, cache.get_block_raw_transactions(&0));
412
413        cache.insert_transaction(H256::zero(), Default::default());
414        assert_eq!(None, cache.get_transaction(&H256::zero()));
415    }
416
417    #[test]
418    fn test_cache_config_memory_enables_cache() {
419        let block_full = Block::<TransactionVariant> {
420            hash: H256::repeat_byte(0x1),
421            number: U64::from(1),
422            ..Default::default()
423        };
424        let block_min = Block::<TransactionVariant> {
425            hash: H256::repeat_byte(0x2),
426            number: U64::from(2),
427            ..Default::default()
428        };
429        let transaction = Transaction::default();
430        let raw_transactions = vec![RawTransaction {
431            common_data: ExecuteTransactionCommon::L1(Default::default()),
432            execute: Execute {
433                calldata: Default::default(),
434                contract_address: Default::default(),
435                factory_deps: vec![],
436                value: Default::default(),
437            },
438            received_timestamp_ms: 0,
439            raw_bytes: None,
440        }];
441        let bridge_addresses = BridgeAddresses {
442            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
443            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
444            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
445            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
446            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
447            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
448            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
449        };
450
451        let mut cache = Cache::new(CacheConfig::Memory);
452
453        cache.insert_block(block_full.hash, true, block_full.clone());
454        assert_eq!(
455            Some(&block_full),
456            cache.get_block(&H256::repeat_byte(0x1), true)
457        );
458        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
459
460        cache.insert_block(block_min.hash, false, block_min.clone());
461        assert_eq!(
462            Some(&block_min),
463            cache.get_block(&H256::repeat_byte(0x2), false)
464        );
465        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
466
467        cache.insert_block_raw_transactions(0, raw_transactions.clone());
468        assert_eq!(
469            Some(&raw_transactions),
470            cache.get_block_raw_transactions(&0)
471        );
472
473        cache.insert_transaction(H256::zero(), transaction.clone());
474        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
475
476        cache.set_bridge_addresses(bridge_addresses.clone());
477        assert_bridge_addresses_eq(
478            &bridge_addresses,
479            cache.get_bridge_addresses().expect("expected addresses"),
480        );
481    }
482
483    #[test]
484    fn test_cache_config_disk_enables_cache_and_preserves_it_to_disk() {
485        let block_full = Block::<TransactionVariant> {
486            hash: H256::repeat_byte(0x1),
487            number: U64::from(1),
488            ..Default::default()
489        };
490        let block_min = Block::<TransactionVariant> {
491            hash: H256::repeat_byte(0x2),
492            number: U64::from(2),
493            ..Default::default()
494        };
495        let transaction = Transaction::default();
496        let raw_transactions = vec![RawTransaction {
497            common_data: ExecuteTransactionCommon::L1(Default::default()),
498            execute: Execute {
499                calldata: Default::default(),
500                contract_address: Default::default(),
501                factory_deps: vec![],
502                value: Default::default(),
503            },
504            received_timestamp_ms: 0,
505            raw_bytes: None,
506        }];
507        let bridge_addresses = BridgeAddresses {
508            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
509            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
510            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
511            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
512            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
513            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
514            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
515        };
516
517        let cache_dir = tempfile::Builder::new()
518            .prefix("cache-test")
519            .tempdir()
520            .expect("failed creating temporary dir");
521        let cache_dir_path = cache_dir
522            .path()
523            .to_str()
524            .expect("invalid dir name")
525            .to_string();
526        let mut cache = Cache::new(CacheConfig::Disk {
527            dir: cache_dir_path.clone(),
528            reset: true,
529        });
530
531        cache.insert_block(block_full.hash, true, block_full.clone());
532        assert_eq!(
533            Some(&block_full),
534            cache.get_block(&H256::repeat_byte(0x1), true)
535        );
536        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
537
538        cache.insert_block(block_min.hash, false, block_min.clone());
539        assert_eq!(
540            Some(&block_min),
541            cache.get_block(&H256::repeat_byte(0x2), false)
542        );
543        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
544
545        cache.insert_block_raw_transactions(0, raw_transactions.clone());
546        assert_eq!(
547            Some(&raw_transactions),
548            cache.get_block_raw_transactions(&0)
549        );
550
551        cache.insert_transaction(H256::zero(), transaction.clone());
552        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
553
554        cache.set_bridge_addresses(bridge_addresses.clone());
555        assert_bridge_addresses_eq(
556            &bridge_addresses,
557            cache.get_bridge_addresses().expect("expected addresses"),
558        );
559
560        let new_cache = Cache::new(CacheConfig::Disk {
561            dir: cache_dir_path,
562            reset: false,
563        });
564        assert_eq!(
565            Some(&block_full),
566            new_cache.get_block(&H256::repeat_byte(0x1), true)
567        );
568        assert_eq!(Some(&H256::repeat_byte(0x1)), new_cache.get_block_hash(&1));
569        assert_eq!(
570            Some(&block_min),
571            new_cache.get_block(&H256::repeat_byte(0x2), false)
572        );
573        assert_eq!(Some(&H256::repeat_byte(0x2)), new_cache.get_block_hash(&2));
574        assert_eq!(
575            Some(&raw_transactions),
576            new_cache.get_block_raw_transactions(&0)
577        );
578        assert_eq!(Some(&transaction), new_cache.get_transaction(&H256::zero()));
579        assert_bridge_addresses_eq(
580            &bridge_addresses,
581            new_cache
582                .get_bridge_addresses()
583                .expect("expected addresses"),
584        );
585    }
586
587    #[test]
588    fn test_cache_config_disk_enables_cache_and_can_reset_data_on_disk() {
589        let block_full = Block::<TransactionVariant> {
590            hash: H256::repeat_byte(0x1),
591            number: U64::from(1),
592            ..Default::default()
593        };
594        let block_min = Block::<TransactionVariant> {
595            hash: H256::repeat_byte(0x2),
596            number: U64::from(2),
597            ..Default::default()
598        };
599        let transaction = Transaction::default();
600        let raw_transactions = vec![RawTransaction {
601            common_data: ExecuteTransactionCommon::L1(Default::default()),
602            execute: Execute {
603                calldata: Default::default(),
604                contract_address: Default::default(),
605                factory_deps: vec![],
606                value: Default::default(),
607            },
608            received_timestamp_ms: 0,
609            raw_bytes: None,
610        }];
611        let bridge_addresses = BridgeAddresses {
612            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
613            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
614            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
615            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
616            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
617            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
618            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
619        };
620
621        let cache_dir = tempfile::Builder::new()
622            .prefix("cache-test")
623            .tempdir()
624            .expect("failed creating temporary dir");
625        let cache_dir_path = cache_dir
626            .path()
627            .to_str()
628            .expect("invalid dir name")
629            .to_string();
630        let mut cache = Cache::new(CacheConfig::Disk {
631            dir: cache_dir_path.clone(),
632            reset: true,
633        });
634
635        cache.insert_block(block_full.hash, true, block_full.clone());
636        assert_eq!(
637            Some(&block_full),
638            cache.get_block(&H256::repeat_byte(0x1), true)
639        );
640        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
641
642        cache.insert_block(block_min.hash, false, block_min.clone());
643        assert_eq!(
644            Some(&block_min),
645            cache.get_block(&H256::repeat_byte(0x2), false)
646        );
647        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
648
649        cache.insert_block_raw_transactions(0, raw_transactions.clone());
650        assert_eq!(
651            Some(&raw_transactions),
652            cache.get_block_raw_transactions(&0)
653        );
654
655        cache.insert_transaction(H256::zero(), transaction.clone());
656        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
657
658        cache.set_bridge_addresses(bridge_addresses.clone());
659        assert_bridge_addresses_eq(
660            &bridge_addresses,
661            cache.get_bridge_addresses().expect("expected addresses"),
662        );
663
664        let new_cache = Cache::new(CacheConfig::Disk {
665            dir: cache_dir_path,
666            reset: true,
667        });
668        assert_eq!(None, new_cache.get_block(&H256::zero(), true));
669        assert_eq!(None, new_cache.get_block_hash(&1));
670        assert_eq!(None, new_cache.get_block(&H256::zero(), false));
671        assert_eq!(None, new_cache.get_block_hash(&2));
672        assert_eq!(None, new_cache.get_block_raw_transactions(&0));
673        assert_eq!(None, new_cache.get_transaction(&H256::zero()));
674        assert!(new_cache.get_bridge_addresses().is_none());
675    }
676
677    #[test]
678    fn test_cache_config_disk_only_resets_created_data_on_disk() {
679        let cache_dir = tempfile::Builder::new()
680            .prefix("cache-test")
681            .tempdir()
682            .expect("failed creating temporary dir");
683        let cache_dir_path = cache_dir
684            .path()
685            .to_str()
686            .expect("invalid dir name")
687            .to_string();
688        let mut cache = Cache::new(CacheConfig::Disk {
689            dir: cache_dir_path.clone(),
690            reset: true,
691        });
692
693        cache.insert_transaction(H256::zero(), Default::default());
694        let cached_tx_file = cache_dir
695            .path()
696            .join(CACHE_TYPE_TRANSACTIONS)
697            .join(format!("{:#x}", H256::zero()));
698        assert!(
699            cached_tx_file.exists(),
700            "cached transaction did not exist on disk"
701        );
702
703        let random_file_path = cache_dir.path().join("foobar.txt");
704        _ = File::create(&random_file_path).expect("failed creating random file");
705
706        Cache::new(CacheConfig::Disk {
707            dir: cache_dir_path,
708            reset: true,
709        });
710
711        assert!(
712            !cached_tx_file.exists(),
713            "cached transaction was not reset on disk"
714        );
715        assert!(random_file_path.exists(), "random file was reset from disk");
716    }
717
718    /// Asserts that two instances of [BridgeAddresses] are equal
719    pub fn assert_bridge_addresses_eq(
720        expected_bridge_addresses: &BridgeAddresses,
721        actual_bridge_addresses: &BridgeAddresses,
722    ) {
723        assert_eq!(
724            expected_bridge_addresses.l1_erc20_default_bridge,
725            actual_bridge_addresses.l1_erc20_default_bridge
726        );
727        assert_eq!(
728            expected_bridge_addresses.l2_erc20_default_bridge,
729            actual_bridge_addresses.l2_erc20_default_bridge
730        );
731        assert_eq!(
732            expected_bridge_addresses.l1_weth_bridge,
733            actual_bridge_addresses.l1_weth_bridge
734        );
735        assert_eq!(
736            expected_bridge_addresses.l2_weth_bridge,
737            actual_bridge_addresses.l2_weth_bridge
738        );
739    }
740}