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