trident_config/
fuzz.rs

1use crate::coverage::Coverage;
2use crate::metrics::Metrics;
3use crate::regression::Regression;
4use crate::utils::resolve_path;
5use base64::prelude::BASE64_STANDARD;
6use base64::Engine;
7use serde::Deserialize;
8use serde::Serialize;
9use solana_sdk::account::AccountSharedData;
10use solana_sdk::account::WritableAccount;
11use solana_sdk::pubkey::Pubkey;
12use std::fs;
13use std::str::FromStr;
14
15#[derive(Debug, Deserialize, Clone, Default)]
16pub struct Fuzz {
17    metrics: Option<Metrics>,
18    regression: Option<Regression>,
19    pub programs: Option<Vec<_FuzzProgram>>,
20    pub accounts: Option<Vec<_FuzzAccount>>,
21    pub coverage: Option<Coverage>,
22}
23
24impl Fuzz {
25    pub fn get_metrics(&self) -> bool {
26        match self.metrics.as_ref() {
27            Some(metrics) => metrics.enabled.unwrap_or(false),
28            None => false,
29        }
30    }
31
32    pub fn get_metrics_json(&self) -> bool {
33        match self.metrics.as_ref() {
34            Some(metrics) => metrics.json.unwrap_or(false),
35            None => false,
36        }
37    }
38
39    pub fn get_metrics_dashboard(&self) -> bool {
40        match self.metrics.as_ref() {
41            Some(metrics) => metrics.dashboard.unwrap_or(false),
42            None => false,
43        }
44    }
45
46    pub fn get_regression(&self) -> bool {
47        match self.regression.as_ref() {
48            Some(regression) => regression.enabled.unwrap_or(false),
49            None => false,
50        }
51    }
52
53    pub fn get_coverage(&self) -> Coverage {
54        self.coverage.clone().unwrap_or_default()
55    }
56}
57
58#[derive(Debug, Deserialize, Clone)]
59pub struct _FuzzProgram {
60    pub address: String,
61    pub upgrade_authority: Option<String>,
62    pub program: String,
63}
64
65#[derive(Debug, Deserialize, Clone)]
66pub struct _FuzzAccount {
67    pub address: String,
68    pub filename: String,
69}
70
71#[derive(Debug, Deserialize, Clone)]
72pub struct FuzzProgram {
73    pub address: Pubkey,
74    pub upgrade_authority: Option<Pubkey>,
75    pub data: Vec<u8>,
76}
77
78impl From<&_FuzzProgram> for FuzzProgram {
79    fn from(_f: &_FuzzProgram) -> Self {
80        let program_path = &_f.program;
81        let program_address = &_f.address;
82
83        let upgrade_authority = _f
84            .upgrade_authority
85            .as_ref()
86            .map(|upgrade_authority| Pubkey::from_str(upgrade_authority).unwrap());
87
88        let path = resolve_path(program_path);
89
90        let program_data =
91            fs::read(path).unwrap_or_else(|_| panic!("Failed to read file: {}", program_path));
92
93        let pubkey = Pubkey::from_str(program_address)
94            .unwrap_or_else(|_| panic!("Cannot parse the program address: {}", program_address));
95
96        FuzzProgram {
97            address: pubkey,
98            upgrade_authority,
99            data: program_data,
100        }
101    }
102}
103
104#[derive(Debug, Deserialize, Clone)]
105pub struct FuzzAccount {
106    pub pubkey: Pubkey,
107    pub account: AccountSharedData,
108}
109
110impl From<&_FuzzAccount> for FuzzAccount {
111    fn from(_f: &_FuzzAccount) -> Self {
112        let account_path = &_f.filename;
113
114        let path = resolve_path(account_path);
115
116        let file_content = fs::read_to_string(path)
117            .unwrap_or_else(|_| panic!("Failed to read file: {}", account_path));
118
119        let account_raw: FuzzAccountRaw = serde_json::from_str(&file_content)
120            .unwrap_or_else(|_| panic!("Failed to parse JSON from file: {}", account_path));
121
122        let pubkey = Pubkey::from_str(&account_raw.pubkey)
123            .unwrap_or_else(|_| panic!("Cannot convert address for: {}", account_raw.pubkey));
124
125        let owner_address = Pubkey::from_str(&account_raw.account.owner).unwrap_or_else(|_| {
126            panic!(
127                "Cannot convert address for owner: {}",
128                account_raw.account.owner
129            )
130        });
131
132        let data_base_64 = account_raw.account.data.first().unwrap_or_else(|| {
133            panic!(
134                "Cannot read base64 data for account: {}",
135                account_raw.pubkey
136            )
137        });
138
139        let account = AccountSharedData::create(
140            account_raw.account.lamports,
141            BASE64_STANDARD
142                .decode(data_base_64)
143                .unwrap_or_else(|_| panic!("Failed to decode base64 data of {}", account_path)),
144            owner_address,
145            account_raw.account.executable,
146            account_raw.account.rent_epoch,
147        );
148
149        FuzzAccount { pubkey, account }
150    }
151}
152
153#[derive(Debug, Deserialize, Clone)]
154pub struct FuzzAccountRaw {
155    pub pubkey: String,
156    pub account: AccountRaw,
157}
158
159#[derive(Debug, Serialize, Deserialize, Clone)]
160pub struct AccountRaw {
161    pub lamports: u64,
162    pub data: Vec<String>,
163    pub owner: String,
164    pub executable: bool,
165    #[serde(rename = "rentEpoch")]
166    pub rent_epoch: u64,
167}