1use crate::felt_deserialize::deserialize as felt_deserialize;
2use camino::Utf8PathBuf;
3use serde::{Deserialize, Serialize};
4use starknet_types_core::felt::Felt;
5use std::collections::HashMap;
6use std::ops::{AddAssign, SubAssign};
7use strum::VariantArray;
8use strum_macros::{Display, EnumString, VariantArray};
9
10#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
11pub struct ClassHash(#[serde(deserialize_with = "felt_deserialize")] pub Felt);
12
13#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
14pub struct ContractAddress(#[serde(deserialize_with = "felt_deserialize")] pub Felt);
15
16#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
17pub struct EntryPointSelector(#[serde(deserialize_with = "felt_deserialize")] pub Felt);
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(untagged)]
24pub enum VersionedCallTrace {
25 V1(CallTraceV1),
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct CallTraceV1 {
32 pub entry_point: CallEntryPoint,
33 #[serde(rename = "used_execution_resources")]
34 pub cumulative_resources: ExecutionResources,
35 pub used_l1_resources: L1Resources,
36 pub nested_calls: Vec<CallTraceNode>,
37 pub cairo_execution_info: Option<CairoExecutionInfo>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct CairoExecutionInfo {
43 pub source_sierra_path: Utf8PathBuf,
45 pub casm_level_info: CasmLevelInfo,
46 pub enable_gas: Option<bool>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct CasmLevelInfo {
52 pub run_with_call_header: bool,
53 pub vm_trace: Vec<TraceEntry>,
54 pub program_offset: Option<usize>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
60pub enum CallTraceNode {
61 EntryPointCall(Box<CallTraceV1>),
62 DeployWithoutConstructor,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct TraceEntry {
67 pub pc: usize,
68 pub ap: usize,
69 pub fp: usize,
70}
71
72type SyscallCounter = HashMap<DeprecatedSyscallSelector, SyscallUsage>;
73
74#[derive(Debug, Default, Clone, Deserialize, Serialize)]
75pub struct SyscallUsage {
76 pub call_count: usize,
77 pub linear_factor: usize,
78}
79
80#[derive(Debug, Default, Clone, Deserialize, Serialize)]
81pub struct ExecutionResources {
82 pub vm_resources: VmExecutionResources,
83 pub gas_consumed: Option<u64>,
84 pub syscall_counter: Option<SyscallCounter>,
86}
87
88#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
89pub struct VmExecutionResources {
90 pub n_steps: usize,
91 pub n_memory_holes: usize,
92 pub builtin_instance_counter: HashMap<String, usize>,
93}
94
95#[derive(
96 Clone,
97 Copy,
98 Debug,
99 Display,
100 Deserialize,
101 Serialize,
102 Eq,
103 Hash,
104 PartialEq,
105 EnumString,
106 VariantArray,
107)]
108pub enum DeprecatedSyscallSelector {
109 CallContract,
110 DelegateCall,
111 DelegateL1Handler,
112 Deploy,
113 EmitEvent,
114 GetBlockHash,
115 GetBlockNumber,
116 GetBlockTimestamp,
117 GetCallerAddress,
118 GetContractAddress,
119 GetClassHashAt,
120 GetExecutionInfo,
121 GetSequencerAddress,
122 GetTxInfo,
123 GetTxSignature,
124 Keccak,
125 LibraryCall,
126 LibraryCallL1Handler,
127 ReplaceClass,
128 Secp256k1Add,
129 Secp256k1GetPointFromX,
130 Secp256k1GetXy,
131 Secp256k1Mul,
132 Secp256k1New,
133 Secp256r1Add,
134 Secp256r1GetPointFromX,
135 Secp256r1GetXy,
136 Secp256r1Mul,
137 Secp256r1New,
138 SendMessageToL1,
139 StorageRead,
140 StorageWrite,
141 Sha256ProcessBlock,
142 Sha512ProcessBlock,
143 KeccakRound,
144 MetaTxV0,
145}
146
147impl DeprecatedSyscallSelector {
148 #[must_use]
149 pub fn all() -> &'static [Self] {
150 Self::VARIANTS
151 }
152}
153
154#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
155pub struct CallEntryPoint {
156 pub class_hash: Option<ClassHash>,
157 pub entry_point_type: EntryPointType,
158 pub entry_point_selector: EntryPointSelector,
159 pub contract_address: ContractAddress,
160 pub call_type: CallType,
161
162 pub contract_name: Option<String>,
164 pub function_name: Option<String>,
166 pub calldata_len: Option<usize>,
169 pub events_summary: Option<Vec<SummedUpEvent>>,
172 pub signature_len: Option<usize>,
175}
176
177#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Deserialize, Serialize)]
178pub enum CallType {
179 #[default]
180 Call = 0,
181 Delegate = 1,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
185pub enum EntryPointType {
186 #[serde(rename = "CONSTRUCTOR")]
187 Constructor,
188 #[serde(rename = "EXTERNAL")]
189 #[default]
190 External,
191 #[serde(rename = "L1_HANDLER")]
192 L1Handler,
193}
194
195#[derive(Clone, Default, Debug, Serialize, Deserialize)]
196pub struct L1Resources {
197 pub l2_l1_message_sizes: Vec<usize>,
198}
199
200impl AddAssign<&VmExecutionResources> for VmExecutionResources {
201 fn add_assign(&mut self, other: &VmExecutionResources) {
202 self.n_steps += other.n_steps;
203 self.n_memory_holes += other.n_memory_holes;
204
205 for (key, value) in &other.builtin_instance_counter {
206 *self
207 .builtin_instance_counter
208 .entry(key.clone())
209 .or_default() += *value;
210 }
211 }
212}
213
214impl SubAssign<&VmExecutionResources> for VmExecutionResources {
215 fn sub_assign(&mut self, other: &VmExecutionResources) {
216 self.n_steps = self.n_steps.saturating_sub(other.n_steps);
217 self.n_memory_holes = self.n_memory_holes.saturating_sub(other.n_memory_holes);
218
219 for (key, value) in &other.builtin_instance_counter {
220 if let Some(self_value) = self.builtin_instance_counter.get_mut(key) {
221 *self_value = self_value.saturating_sub(*value);
222 }
223 }
224 self.builtin_instance_counter.retain(|_, value| *value > 0);
226 }
227}
228
229impl AddAssign<&ExecutionResources> for ExecutionResources {
230 fn add_assign(&mut self, other: &ExecutionResources) {
231 self.vm_resources += &other.vm_resources;
232 self.gas_consumed = match (self.gas_consumed, other.gas_consumed) {
233 (Some(self_gas), Some(other_gas)) => Some(self_gas + other_gas),
234 (Some(self_gas), None) => Some(self_gas),
235 (None, Some(other_gas)) => Some(other_gas),
236 (None, None) => None,
237 };
238
239 if let Some(other_counter) = &other.syscall_counter {
240 let self_counter = self.syscall_counter.get_or_insert_with(HashMap::new);
241 for (&selector, usage) in other_counter {
242 self_counter
243 .entry(selector)
244 .and_modify(|existing| {
245 existing.call_count += usage.call_count;
246 existing.linear_factor += usage.linear_factor;
247 })
248 .or_insert_with(|| usage.clone());
249 }
250 }
251 }
252}
253
254impl SubAssign<&ExecutionResources> for ExecutionResources {
255 fn sub_assign(&mut self, other: &ExecutionResources) {
256 self.vm_resources -= &other.vm_resources;
257
258 if let Some(other_gas) = other.gas_consumed
259 && let Some(self_gas) = &mut self.gas_consumed
260 {
261 *self_gas = self_gas.saturating_sub(other_gas);
262 }
263
264 if let Some(self_counter) = &mut self.syscall_counter
265 && let Some(other_counter) = &other.syscall_counter
266 {
267 for (selector, usage) in other_counter {
268 if let Some(self_usage) = self_counter.get_mut(selector) {
269 self_usage.call_count = self_usage.call_count.saturating_sub(usage.call_count);
270 self_usage.linear_factor =
271 self_usage.linear_factor.saturating_sub(usage.linear_factor);
272 }
273 }
274 self_counter.retain(|_, usage| usage.call_count > 0 || usage.linear_factor > 0);
276 }
277 }
278}
279
280#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
281pub struct SummedUpEvent {
282 pub keys_len: usize,
283 pub data_len: usize,
284}