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}