arbiter_core/database/fork.rs
1//! This module contains the [`Fork`] struct which is used to store the data
2//! that will be loaded into an [`Environment`] and be used in `arbiter-core`.
3//! [`Fork`] contains a [`CacheDB`] and [`ContractMetadata`] so
4//! that the [`Environment`] can be initialized with a forked database and the
5//! end-user still has access to the relevant metadata.
6
7use std::{env, fs};
8
9use super::*;
10
11/// A [`ContractMetadata`] is used to store the metadata of a contract that will
12/// be loaded into a [`Fork`].
13#[derive(Clone, Debug, Deserialize, Serialize)]
14pub struct ContractMetadata {
15 /// The address of the contract.
16 pub address: eAddress,
17
18 /// The path to the contract artifacts.
19 pub artifacts_path: String,
20
21 /// The mappings that are part of the contract's storage.
22 pub mappings: HashMap<String, Vec<String>>,
23}
24
25/// A [`Fork`] is used to store the data that will be loaded into an
26/// [`Environment`] and be used in `arbiter-core`. It is a wrapper around a
27/// [`CacheDB`] and a [`HashMap`] of [`ContractMetadata`] so that the
28/// [`environment::Environment`] can be initialized with the data and the
29/// end-user still has access to the relevant metadata.
30#[derive(Clone, Debug)]
31pub struct Fork {
32 /// The [`CacheDB`] that will be loaded into the [`Environment`].
33 pub db: CacheDB<EmptyDB>,
34
35 /// The [`HashMap`] of [`ContractMetadata`] that will be used by the
36 /// end-user.
37 pub contracts_meta: HashMap<String, ContractMetadata>,
38 /// The [`HashMap`] of [`Address`] that will be used by the end-user.
39 pub eoa: HashMap<String, eAddress>,
40}
41
42impl Fork {
43 /// Creates a new [`Fork`] from serialized [`DiskData`] stored on disk.
44 pub fn from_disk(path: &str) -> Result<Self, ArbiterCoreError> {
45 // Read the file
46 let mut cwd = env::current_dir().unwrap();
47 cwd.push(path);
48 print!("Reading db from: {:?}", cwd);
49 let data = fs::read_to_string(cwd).unwrap();
50
51 // Deserialize the JSON data to your OutputData type
52 let disk_data: DiskData = serde_json::from_str(&data).unwrap();
53
54 // Create a CacheDB instance
55 let mut db = CacheDB::new(EmptyDB::default());
56
57 // Populate the CacheDB from the OutputData
58 for (address, (info, storage_map)) in disk_data.raw {
59 // Convert the string address back to its original type
60 let address = address.as_fixed_bytes().into(); // You'd need to define this
61
62 // Insert account info into the DB
63 db.insert_account_info(address, info);
64
65 // Insert storage data into the DB
66 for (key_str, value_str) in storage_map {
67 let key = U256::from_str_radix(&key_str, 10).unwrap();
68 let value = U256::from_str_radix(&value_str, 10).unwrap();
69
70 db.insert_account_storage(address, key, value).unwrap();
71 }
72 }
73
74 Ok(Self {
75 db,
76 contracts_meta: disk_data.meta,
77 eoa: disk_data.externally_owned_accounts,
78 })
79 }
80}
81
82impl From<Fork> for CacheDB<EmptyDB> {
83 fn from(val: Fork) -> Self {
84 val.db
85 }
86}
87
88type Storage = HashMap<String, String>;
89
90/// This is the data that will be written to and loaded from disk to generate a
91/// [`Fork`].
92#[derive(Debug, Serialize, Deserialize)]
93pub struct DiskData {
94 /// This is the metadata for the contracts that will be loaded into the
95 /// [`Fork`].
96 pub meta: HashMap<String, ContractMetadata>,
97
98 /// This is the raw data that will be loaded into the [`Fork`].
99 pub raw: HashMap<eAddress, (AccountInfo, Storage)>,
100
101 /// This is the eoa data that will be loaded into the [`Fork`].
102 pub externally_owned_accounts: HashMap<String, eAddress>,
103}