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::api::{Block, BridgeAddresses, Transaction, TransactionVariant};
12use zksync_types::Transaction as RawTransaction;
13use zksync_types::H256;
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!("{:#x}", hash), &block);
157            self.blocks_full.insert(hash, block);
158        } else {
159            self.write_to_disk(CACHE_TYPE_BLOCKS_MIN, format!("{:#x}", hash), &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    /// Returns the cached confirmed tokens.
183    pub fn get_confirmed_tokens(
184        &self,
185        from: u32,
186        limit: u8,
187    ) -> Option<&Vec<zksync_web3_decl::types::Token>> {
188        if matches!(self.config, CacheConfig::None) {
189            return None;
190        }
191        self.confirmed_tokens.get(&(from, limit))
192    }
193
194    /// Cache confirmed tokens
195    pub fn set_confirmed_tokens(
196        &mut self,
197        from: u32,
198        limit: u8,
199        confirmed_tokens: Vec<zksync_web3_decl::types::Token>,
200    ) {
201        if matches!(self.config, CacheConfig::None) {
202            return;
203        }
204        self.confirmed_tokens
205            .insert((from, limit), confirmed_tokens);
206    }
207
208    /// Cache the raw transactions for the provided block number.
209    pub fn insert_block_raw_transactions(
210        &mut self,
211        number: u64,
212        transactions: Vec<RawTransaction>,
213    ) {
214        if matches!(self.config, CacheConfig::None) {
215            return;
216        }
217
218        self.write_to_disk(
219            CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
220            format!("{}", number),
221            &transactions,
222        );
223        self.block_raw_transactions.insert(number, transactions);
224    }
225
226    /// Returns the cached transaction for the provided hash.
227    pub fn get_transaction(&self, hash: &H256) -> Option<&Transaction> {
228        if matches!(self.config, CacheConfig::None) {
229            return None;
230        }
231
232        self.transactions.get(hash)
233    }
234
235    /// Returns the cached resolved function/event selector for the provided selector.
236    pub fn get_resolver_selector(&self, selector: &String) -> Option<&String> {
237        if matches!(self.config, CacheConfig::None) {
238            return None;
239        }
240
241        self.resolver_selectors.get(selector)
242    }
243
244    /// Cache a transaction for the provided hash.
245    pub fn insert_transaction(&mut self, hash: H256, transaction: Transaction) {
246        if matches!(self.config, CacheConfig::None) {
247            return;
248        }
249
250        self.write_to_disk(
251            CACHE_TYPE_TRANSACTIONS,
252            format!("{:#x}", hash),
253            &transaction,
254        );
255        self.transactions.insert(hash, transaction);
256    }
257
258    /// Cache a resolver function for the provided selector.
259    pub fn insert_resolver_selector(&mut self, selector: String, selector_value: String) {
260        if matches!(self.config, CacheConfig::None) {
261            return;
262        }
263
264        self.write_to_disk(
265            CACHE_TYPE_RESOLVER_SELECTORS,
266            selector.clone(),
267            &selector_value,
268        );
269        self.resolver_selectors.insert(selector, selector_value);
270    }
271
272    /// Returns the cached bridge addresses for the provided hash.
273    pub fn get_bridge_addresses(&self) -> Option<&BridgeAddresses> {
274        if matches!(self.config, CacheConfig::None) {
275            return None;
276        }
277
278        self.bridge_addresses.as_ref()
279    }
280
281    /// Cache default bridge addresses.
282    pub fn set_bridge_addresses(&mut self, bridge_addresses: BridgeAddresses) {
283        if matches!(self.config, CacheConfig::None) {
284            return;
285        }
286
287        self.write_to_disk(
288            CACHE_TYPE_KEY_VALUE,
289            String::from(CACHE_KEY_BRIDGE_ADDRESSES),
290            &bridge_addresses,
291        );
292        self.bridge_addresses = Some(bridge_addresses);
293    }
294
295    /// Reads the cache contents from the disk, if available.
296    fn read_all_from_disk(&mut self, dir: &str) -> Result<(), String> {
297        for cache_type in [
298            CACHE_TYPE_BLOCKS_FULL,
299            CACHE_TYPE_BLOCKS_MIN,
300            CACHE_TYPE_BLOCK_RAW_TRANSACTIONS,
301            CACHE_TYPE_TRANSACTIONS,
302            CACHE_TYPE_RESOLVER_SELECTORS,
303            CACHE_TYPE_KEY_VALUE,
304        ] {
305            let cache_dir = Path::new(dir).join(cache_type);
306            let dir_listing = fs::read_dir(cache_dir.clone())
307                .map_err(|err| format!("failed reading dir '{:?}': {:?}", cache_dir, err))?
308                .flatten();
309            for file in dir_listing {
310                let key = file
311                    .file_name()
312                    .to_str()
313                    .ok_or_else(|| String::from("failed converting filename to string"))?
314                    .to_string();
315
316                let cache_file = File::open(file.path()).map_err(|err| {
317                    format!("failed reading file: '{:?}': {:?}", file.path(), err)
318                })?;
319                let reader = BufReader::new(cache_file);
320                match cache_type {
321                    CACHE_TYPE_BLOCKS_FULL => {
322                        let key = H256::from_str(&key).map_err(|err| {
323                            format!("invalid key for cache file '{:?}': {:?}", key, err)
324                        })?;
325                        let block: Block<TransactionVariant> = serde_json::from_reader(reader)
326                            .map_err(|err| {
327                                format!("failed parsing json for cache file '{:?}': {:?}", key, err)
328                            })?;
329                        self.block_hashes.insert(block.number.as_u64(), block.hash);
330                        self.blocks_full.insert(key, block);
331                    }
332                    CACHE_TYPE_BLOCKS_MIN => {
333                        let key = H256::from_str(&key).map_err(|err| {
334                            format!("invalid key for cache file '{:?}': {:?}", key, err)
335                        })?;
336                        let block: Block<TransactionVariant> = serde_json::from_reader(reader)
337                            .map_err(|err| {
338                                format!("failed parsing json for cache file '{:?}': {:?}", key, err)
339                            })?;
340                        self.block_hashes.insert(block.number.as_u64(), block.hash);
341                        self.blocks_min.insert(key, block);
342                    }
343                    CACHE_TYPE_BLOCK_RAW_TRANSACTIONS => {
344                        let key = key.parse::<u64>().map_err(|err| {
345                            format!("invalid key for cache file '{:?}': {:?}", key, err)
346                        })?;
347                        let transactions: Vec<RawTransaction> = serde_json::from_reader(reader)
348                            .map_err(|err| {
349                                format!("failed parsing json for cache file '{:?}': {:?}", key, err)
350                            })?;
351                        self.block_raw_transactions.insert(key, transactions);
352                    }
353                    CACHE_TYPE_TRANSACTIONS => {
354                        let key = H256::from_str(&key).map_err(|err| {
355                            format!("invalid key for cache file '{:?}': {:?}", key, err)
356                        })?;
357                        let transaction: Transaction =
358                            serde_json::from_reader(reader).map_err(|err| {
359                                format!("failed parsing json for cache file '{:?}': {:?}", key, err)
360                            })?;
361                        self.transactions.insert(key, transaction);
362                    }
363                    CACHE_TYPE_RESOLVER_SELECTORS => {
364                        let selector: String = serde_json::from_reader(reader).map_err(|err| {
365                            format!("failed parsing json for cache file '{:?}': {:?}", key, err)
366                        })?;
367                        self.resolver_selectors.insert(key, selector);
368                    }
369                    CACHE_TYPE_KEY_VALUE => match key.as_str() {
370                        CACHE_KEY_BRIDGE_ADDRESSES => {
371                            self.bridge_addresses =
372                                Some(serde_json::from_reader(reader).map_err(|err| {
373                                    format!(
374                                        "failed parsing json for cache file '{:?}': {:?}",
375                                        key, err
376                                    )
377                                })?);
378                        }
379                        _ => return Err(format!("invalid cache_type_value key {}", cache_type)),
380                    },
381                    _ => return Err(format!("invalid cache_type {}", cache_type)),
382                }
383            }
384        }
385
386        Ok(())
387    }
388
389    /// Writes the cache contents to disk, if supported.
390    fn write_to_disk<T: Serialize>(&self, cache_type: &'static str, key: String, data: &T) {
391        if let CacheConfig::Disk { dir, .. } = &self.config {
392            let file = Path::new(&dir).join(cache_type).join(key);
393
394            tracing::debug!("writing cache {:?}", file);
395            match File::create(file.clone()) {
396                Ok(cache_file) => {
397                    let writer = BufWriter::new(cache_file);
398                    if let Err(err) = serde_json::to_writer(writer, data) {
399                        sh_err!("failed writing to cache '{:?}': {:?}", file, err);
400                    }
401                }
402                Err(err) => sh_err!("failed creating file: '{:?}': {:?}", file, err),
403            }
404        }
405    }
406}
407
408#[cfg(test)]
409mod tests {
410    use zksync_types::{Execute, ExecuteTransactionCommon};
411    use zksync_types::{H160, U64};
412
413    // use crate::testing;
414
415    use super::*;
416
417    #[test]
418    fn test_cache_config_none_disables_cache() {
419        let mut cache = Cache::new(CacheConfig::None);
420
421        cache.insert_block(H256::zero(), true, Default::default());
422        assert_eq!(None, cache.get_block(&H256::zero(), true));
423        assert_eq!(None, cache.get_block_hash(&0));
424
425        cache.insert_block(H256::zero(), false, Default::default());
426        assert_eq!(None, cache.get_block(&H256::zero(), false));
427        assert_eq!(None, cache.get_block_hash(&0));
428
429        cache.insert_block_raw_transactions(0, Default::default());
430        assert_eq!(None, cache.get_block_raw_transactions(&0));
431
432        cache.insert_transaction(H256::zero(), Default::default());
433        assert_eq!(None, cache.get_transaction(&H256::zero()));
434    }
435
436    #[test]
437    fn test_cache_config_memory_enables_cache() {
438        let block_full = Block::<TransactionVariant> {
439            hash: H256::repeat_byte(0x1),
440            number: U64::from(1),
441            ..Default::default()
442        };
443        let block_min = Block::<TransactionVariant> {
444            hash: H256::repeat_byte(0x2),
445            number: U64::from(2),
446            ..Default::default()
447        };
448        let transaction = Transaction::default();
449        let raw_transactions = vec![RawTransaction {
450            common_data: ExecuteTransactionCommon::L1(Default::default()),
451            execute: Execute {
452                calldata: Default::default(),
453                contract_address: Default::default(),
454                factory_deps: vec![],
455                value: Default::default(),
456            },
457            received_timestamp_ms: 0,
458            raw_bytes: None,
459        }];
460        let bridge_addresses = BridgeAddresses {
461            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
462            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
463            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
464            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
465            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
466            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
467            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
468        };
469
470        let mut cache = Cache::new(CacheConfig::Memory);
471
472        cache.insert_block(block_full.hash, true, block_full.clone());
473        assert_eq!(
474            Some(&block_full),
475            cache.get_block(&H256::repeat_byte(0x1), true)
476        );
477        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
478
479        cache.insert_block(block_min.hash, false, block_min.clone());
480        assert_eq!(
481            Some(&block_min),
482            cache.get_block(&H256::repeat_byte(0x2), false)
483        );
484        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
485
486        cache.insert_block_raw_transactions(0, raw_transactions.clone());
487        assert_eq!(
488            Some(&raw_transactions),
489            cache.get_block_raw_transactions(&0)
490        );
491
492        cache.insert_transaction(H256::zero(), transaction.clone());
493        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
494
495        cache.set_bridge_addresses(bridge_addresses.clone());
496        assert_bridge_addresses_eq(
497            &bridge_addresses,
498            cache.get_bridge_addresses().expect("expected addresses"),
499        );
500    }
501
502    #[test]
503    fn test_cache_config_disk_enables_cache_and_preserves_it_to_disk() {
504        let block_full = Block::<TransactionVariant> {
505            hash: H256::repeat_byte(0x1),
506            number: U64::from(1),
507            ..Default::default()
508        };
509        let block_min = Block::<TransactionVariant> {
510            hash: H256::repeat_byte(0x2),
511            number: U64::from(2),
512            ..Default::default()
513        };
514        let transaction = Transaction::default();
515        let raw_transactions = vec![RawTransaction {
516            common_data: ExecuteTransactionCommon::L1(Default::default()),
517            execute: Execute {
518                calldata: Default::default(),
519                contract_address: Default::default(),
520                factory_deps: vec![],
521                value: Default::default(),
522            },
523            received_timestamp_ms: 0,
524            raw_bytes: None,
525        }];
526        let bridge_addresses = BridgeAddresses {
527            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
528            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
529            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
530            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
531            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
532            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
533            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
534        };
535
536        let cache_dir = tempfile::Builder::new()
537            .prefix("cache-test")
538            .tempdir()
539            .expect("failed creating temporary dir");
540        let cache_dir_path = cache_dir
541            .path()
542            .to_str()
543            .expect("invalid dir name")
544            .to_string();
545        let mut cache = Cache::new(CacheConfig::Disk {
546            dir: cache_dir_path.clone(),
547            reset: true,
548        });
549
550        cache.insert_block(block_full.hash, true, block_full.clone());
551        assert_eq!(
552            Some(&block_full),
553            cache.get_block(&H256::repeat_byte(0x1), true)
554        );
555        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
556
557        cache.insert_block(block_min.hash, false, block_min.clone());
558        assert_eq!(
559            Some(&block_min),
560            cache.get_block(&H256::repeat_byte(0x2), false)
561        );
562        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
563
564        cache.insert_block_raw_transactions(0, raw_transactions.clone());
565        assert_eq!(
566            Some(&raw_transactions),
567            cache.get_block_raw_transactions(&0)
568        );
569
570        cache.insert_transaction(H256::zero(), transaction.clone());
571        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
572
573        cache.set_bridge_addresses(bridge_addresses.clone());
574        assert_bridge_addresses_eq(
575            &bridge_addresses,
576            cache.get_bridge_addresses().expect("expected addresses"),
577        );
578
579        let new_cache = Cache::new(CacheConfig::Disk {
580            dir: cache_dir_path,
581            reset: false,
582        });
583        assert_eq!(
584            Some(&block_full),
585            new_cache.get_block(&H256::repeat_byte(0x1), true)
586        );
587        assert_eq!(Some(&H256::repeat_byte(0x1)), new_cache.get_block_hash(&1));
588        assert_eq!(
589            Some(&block_min),
590            new_cache.get_block(&H256::repeat_byte(0x2), false)
591        );
592        assert_eq!(Some(&H256::repeat_byte(0x2)), new_cache.get_block_hash(&2));
593        assert_eq!(
594            Some(&raw_transactions),
595            new_cache.get_block_raw_transactions(&0)
596        );
597        assert_eq!(Some(&transaction), new_cache.get_transaction(&H256::zero()));
598        assert_bridge_addresses_eq(
599            &bridge_addresses,
600            new_cache
601                .get_bridge_addresses()
602                .expect("expected addresses"),
603        );
604    }
605
606    #[test]
607    fn test_cache_config_disk_enables_cache_and_can_reset_data_on_disk() {
608        let block_full = Block::<TransactionVariant> {
609            hash: H256::repeat_byte(0x1),
610            number: U64::from(1),
611            ..Default::default()
612        };
613        let block_min = Block::<TransactionVariant> {
614            hash: H256::repeat_byte(0x2),
615            number: U64::from(2),
616            ..Default::default()
617        };
618        let transaction = Transaction::default();
619        let raw_transactions = vec![RawTransaction {
620            common_data: ExecuteTransactionCommon::L1(Default::default()),
621            execute: Execute {
622                calldata: Default::default(),
623                contract_address: Default::default(),
624                factory_deps: vec![],
625                value: Default::default(),
626            },
627            received_timestamp_ms: 0,
628            raw_bytes: None,
629        }];
630        let bridge_addresses = BridgeAddresses {
631            l1_shared_default_bridge: Some(H160::repeat_byte(0x5)),
632            l2_shared_default_bridge: Some(H160::repeat_byte(0x6)),
633            l2_erc20_default_bridge: Some(H160::repeat_byte(0x2)),
634            l1_erc20_default_bridge: Some(H160::repeat_byte(0x1)),
635            l1_weth_bridge: Some(H160::repeat_byte(0x3)),
636            l2_weth_bridge: Some(H160::repeat_byte(0x4)),
637            l2_legacy_shared_bridge: Some(H160::repeat_byte(0x6)),
638        };
639
640        let cache_dir = tempfile::Builder::new()
641            .prefix("cache-test")
642            .tempdir()
643            .expect("failed creating temporary dir");
644        let cache_dir_path = cache_dir
645            .path()
646            .to_str()
647            .expect("invalid dir name")
648            .to_string();
649        let mut cache = Cache::new(CacheConfig::Disk {
650            dir: cache_dir_path.clone(),
651            reset: true,
652        });
653
654        cache.insert_block(block_full.hash, true, block_full.clone());
655        assert_eq!(
656            Some(&block_full),
657            cache.get_block(&H256::repeat_byte(0x1), true)
658        );
659        assert_eq!(Some(&H256::repeat_byte(0x1)), cache.get_block_hash(&1));
660
661        cache.insert_block(block_min.hash, false, block_min.clone());
662        assert_eq!(
663            Some(&block_min),
664            cache.get_block(&H256::repeat_byte(0x2), false)
665        );
666        assert_eq!(Some(&H256::repeat_byte(0x2)), cache.get_block_hash(&2));
667
668        cache.insert_block_raw_transactions(0, raw_transactions.clone());
669        assert_eq!(
670            Some(&raw_transactions),
671            cache.get_block_raw_transactions(&0)
672        );
673
674        cache.insert_transaction(H256::zero(), transaction.clone());
675        assert_eq!(Some(&transaction), cache.get_transaction(&H256::zero()));
676
677        cache.set_bridge_addresses(bridge_addresses.clone());
678        assert_bridge_addresses_eq(
679            &bridge_addresses,
680            cache.get_bridge_addresses().expect("expected addresses"),
681        );
682
683        let new_cache = Cache::new(CacheConfig::Disk {
684            dir: cache_dir_path,
685            reset: true,
686        });
687        assert_eq!(None, new_cache.get_block(&H256::zero(), true));
688        assert_eq!(None, new_cache.get_block_hash(&1));
689        assert_eq!(None, new_cache.get_block(&H256::zero(), false));
690        assert_eq!(None, new_cache.get_block_hash(&2));
691        assert_eq!(None, new_cache.get_block_raw_transactions(&0));
692        assert_eq!(None, new_cache.get_transaction(&H256::zero()));
693        assert!(new_cache.get_bridge_addresses().is_none());
694    }
695
696    #[test]
697    fn test_cache_config_disk_only_resets_created_data_on_disk() {
698        let cache_dir = tempfile::Builder::new()
699            .prefix("cache-test")
700            .tempdir()
701            .expect("failed creating temporary dir");
702        let cache_dir_path = cache_dir
703            .path()
704            .to_str()
705            .expect("invalid dir name")
706            .to_string();
707        let mut cache = Cache::new(CacheConfig::Disk {
708            dir: cache_dir_path.clone(),
709            reset: true,
710        });
711
712        cache.insert_transaction(H256::zero(), Default::default());
713        let cached_tx_file = cache_dir
714            .path()
715            .join(CACHE_TYPE_TRANSACTIONS)
716            .join(format!("{:#x}", H256::zero()));
717        assert!(
718            cached_tx_file.exists(),
719            "cached transaction did not exist on disk"
720        );
721
722        let random_file_path = cache_dir.path().join("foobar.txt");
723        _ = File::create(&random_file_path).expect("failed creating random file");
724
725        Cache::new(CacheConfig::Disk {
726            dir: cache_dir_path,
727            reset: true,
728        });
729
730        assert!(
731            !cached_tx_file.exists(),
732            "cached transaction was not reset on disk"
733        );
734        assert!(random_file_path.exists(), "random file was reset from disk");
735    }
736
737    /// Asserts that two instances of [BridgeAddresses] are equal
738    pub fn assert_bridge_addresses_eq(
739        expected_bridge_addresses: &BridgeAddresses,
740        actual_bridge_addresses: &BridgeAddresses,
741    ) {
742        assert_eq!(
743            expected_bridge_addresses.l1_erc20_default_bridge,
744            actual_bridge_addresses.l1_erc20_default_bridge
745        );
746        assert_eq!(
747            expected_bridge_addresses.l2_erc20_default_bridge,
748            actual_bridge_addresses.l2_erc20_default_bridge
749        );
750        assert_eq!(
751            expected_bridge_addresses.l1_weth_bridge,
752            actual_bridge_addresses.l1_weth_bridge
753        );
754        assert_eq!(
755            expected_bridge_addresses.l2_weth_bridge,
756            actual_bridge_addresses.l2_weth_bridge
757        );
758    }
759}