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 KeccakRound,
143 MetaTxV0,
144}
145
146impl DeprecatedSyscallSelector {
147 #[must_use]
148 pub fn all() -> &'static [Self] {
149 Self::VARIANTS
150 }
151}
152
153#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
154pub struct CallEntryPoint {
155 pub class_hash: Option<ClassHash>,
156 pub entry_point_type: EntryPointType,
157 pub entry_point_selector: EntryPointSelector,
158 pub contract_address: ContractAddress,
159 pub call_type: CallType,
160
161 pub contract_name: Option<String>,
163 pub function_name: Option<String>,
165 pub calldata_len: Option<usize>,
168 pub events_summary: Option<Vec<SummedUpEvent>>,
171 pub signature_len: Option<usize>,
174}
175
176#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Deserialize, Serialize)]
177pub enum CallType {
178 #[default]
179 Call = 0,
180 Delegate = 1,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
184pub enum EntryPointType {
185 #[serde(rename = "CONSTRUCTOR")]
186 Constructor,
187 #[serde(rename = "EXTERNAL")]
188 #[default]
189 External,
190 #[serde(rename = "L1_HANDLER")]
191 L1Handler,
192}
193
194#[derive(Clone, Default, Debug, Serialize, Deserialize)]
195pub struct L1Resources {
196 pub l2_l1_message_sizes: Vec<usize>,
197}
198
199impl AddAssign<&VmExecutionResources> for VmExecutionResources {
200 fn add_assign(&mut self, other: &VmExecutionResources) {
201 self.n_steps += other.n_steps;
202 self.n_memory_holes += other.n_memory_holes;
203
204 for (key, value) in &other.builtin_instance_counter {
205 *self
206 .builtin_instance_counter
207 .entry(key.clone())
208 .or_default() += *value;
209 }
210 }
211}
212
213impl SubAssign<&VmExecutionResources> for VmExecutionResources {
214 fn sub_assign(&mut self, other: &VmExecutionResources) {
215 self.n_steps = self.n_steps.saturating_sub(other.n_steps);
216 self.n_memory_holes = self.n_memory_holes.saturating_sub(other.n_memory_holes);
217
218 for (key, value) in &other.builtin_instance_counter {
219 if let Some(self_value) = self.builtin_instance_counter.get_mut(key) {
220 *self_value = self_value.saturating_sub(*value);
221 }
222 }
223 self.builtin_instance_counter.retain(|_, value| *value > 0);
225 }
226}
227
228impl AddAssign<&ExecutionResources> for ExecutionResources {
229 fn add_assign(&mut self, other: &ExecutionResources) {
230 self.vm_resources += &other.vm_resources;
231 self.gas_consumed = match (self.gas_consumed, other.gas_consumed) {
232 (Some(self_gas), Some(other_gas)) => Some(self_gas + other_gas),
233 (Some(self_gas), None) => Some(self_gas),
234 (None, Some(other_gas)) => Some(other_gas),
235 (None, None) => None,
236 };
237
238 if let Some(other_counter) = &other.syscall_counter {
239 let self_counter = self.syscall_counter.get_or_insert_with(HashMap::new);
240 for (&selector, usage) in other_counter {
241 self_counter
242 .entry(selector)
243 .and_modify(|existing| {
244 existing.call_count += usage.call_count;
245 existing.linear_factor += usage.linear_factor;
246 })
247 .or_insert_with(|| usage.clone());
248 }
249 }
250 }
251}
252
253impl SubAssign<&ExecutionResources> for ExecutionResources {
254 fn sub_assign(&mut self, other: &ExecutionResources) {
255 self.vm_resources -= &other.vm_resources;
256
257 if let Some(other_gas) = other.gas_consumed
258 && let Some(self_gas) = &mut self.gas_consumed
259 {
260 *self_gas = self_gas.saturating_sub(other_gas);
261 }
262
263 if let Some(self_counter) = &mut self.syscall_counter
264 && let Some(other_counter) = &other.syscall_counter
265 {
266 for (selector, usage) in other_counter {
267 if let Some(self_usage) = self_counter.get_mut(selector) {
268 self_usage.call_count = self_usage.call_count.saturating_sub(usage.call_count);
269 self_usage.linear_factor =
270 self_usage.linear_factor.saturating_sub(usage.linear_factor);
271 }
272 }
273 self_counter.retain(|_, usage| usage.call_count > 0 || usage.linear_factor > 0);
275 }
276 }
277}
278
279#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)]
280pub struct SummedUpEvent {
281 pub keys_len: usize,
282 pub data_len: usize,
283}