1use crate::{
2 stdlib::{
3 collections::{BTreeMap, HashMap},
4 prelude::{String, Vec},
5 },
6 types::builtin_name::BuiltinName,
7};
8use serde::{Deserialize, Serialize};
9
10use crate::Felt252;
11
12#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
14pub struct AirPrivateInputSerializable {
15 trace_path: String,
16 memory_path: String,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pedersen: Option<Vec<PrivateInput>>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 range_check: Option<Vec<PrivateInput>>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 range_check96: Option<Vec<PrivateInput>>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 ecdsa: Option<Vec<PrivateInput>>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 bitwise: Option<Vec<PrivateInput>>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 ec_op: Option<Vec<PrivateInput>>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 keccak: Option<Vec<PrivateInput>>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 poseidon: Option<Vec<PrivateInput>>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 add_mod: Option<PrivateInput>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 mul_mod: Option<PrivateInput>,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
41pub struct AirPrivateInput(pub HashMap<BuiltinName, Vec<PrivateInput>>);
42
43#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
44#[serde(untagged)]
45pub enum PrivateInput {
46 Value(PrivateInputValue),
47 Pair(PrivateInputPair),
48 EcOp(PrivateInputEcOp),
49 PoseidonState(PrivateInputPoseidonState),
50 KeccakState(PrivateInputKeccakState),
51 Signature(PrivateInputSignature),
52 Mod(ModInput),
53}
54
55#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
56pub struct PrivateInputValue {
57 pub index: usize,
58 pub value: Felt252,
59}
60
61#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
62pub struct PrivateInputPair {
63 pub index: usize,
64 pub x: Felt252,
65 pub y: Felt252,
66}
67
68#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
69pub struct PrivateInputEcOp {
70 pub index: usize,
71 pub p_x: Felt252,
72 pub p_y: Felt252,
73 pub m: Felt252,
74 pub q_x: Felt252,
75 pub q_y: Felt252,
76}
77
78#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
79pub struct PrivateInputPoseidonState {
80 pub index: usize,
81 pub input_s0: Felt252,
82 pub input_s1: Felt252,
83 pub input_s2: Felt252,
84}
85
86#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
87pub struct PrivateInputKeccakState {
88 pub index: usize,
89 pub input_s0: Felt252,
90 pub input_s1: Felt252,
91 pub input_s2: Felt252,
92 pub input_s3: Felt252,
93 pub input_s4: Felt252,
94 pub input_s5: Felt252,
95 pub input_s6: Felt252,
96 pub input_s7: Felt252,
97}
98
99#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
100pub struct PrivateInputSignature {
101 pub index: usize,
102 pub pubkey: Felt252,
103 pub msg: Felt252,
104 pub signature_input: SignatureInput,
105}
106
107#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
108pub struct SignatureInput {
109 pub r: Felt252,
110 pub w: Felt252,
111}
112
113#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
114pub struct ModInput {
115 pub instances: Vec<ModInputInstance>,
116 pub zero_value_address: usize,
117}
118
119#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
120pub struct ModInputInstance {
121 pub index: usize,
122 pub p0: Felt252,
123 pub p1: Felt252,
124 pub p2: Felt252,
125 pub p3: Felt252,
126 pub values_ptr: usize,
127 pub offsets_ptr: usize,
128 pub n: usize,
129 #[serde(deserialize_with = "mod_input_instance_batch_serde::deserialize")]
130 #[serde(serialize_with = "mod_input_instance_batch_serde::serialize")]
131 pub batch: BTreeMap<usize, ModInputMemoryVars>,
132}
133
134#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
135pub struct ModInputMemoryVars {
136 pub a_offset: usize,
137 pub a0: Felt252,
138 pub a1: Felt252,
139 pub a2: Felt252,
140 pub a3: Felt252,
141 pub b_offset: usize,
142 pub b0: Felt252,
143 pub b1: Felt252,
144 pub b2: Felt252,
145 pub b3: Felt252,
146 pub c_offset: usize,
147 pub c0: Felt252,
148 pub c1: Felt252,
149 pub c2: Felt252,
150 pub c3: Felt252,
151}
152
153impl AirPrivateInput {
154 pub fn to_serializable(
155 &self,
156 trace_path: String,
157 memory_path: String,
158 ) -> AirPrivateInputSerializable {
159 AirPrivateInputSerializable {
160 trace_path,
161 memory_path,
162 pedersen: self.0.get(&BuiltinName::pedersen).cloned(),
163 range_check: self.0.get(&BuiltinName::range_check).cloned(),
164 range_check96: self.0.get(&BuiltinName::range_check96).cloned(),
165 ecdsa: self.0.get(&BuiltinName::ecdsa).cloned(),
166 bitwise: self.0.get(&BuiltinName::bitwise).cloned(),
167 ec_op: self.0.get(&BuiltinName::ec_op).cloned(),
168 keccak: self.0.get(&BuiltinName::keccak).cloned(),
169 poseidon: self.0.get(&BuiltinName::poseidon).cloned(),
170 add_mod: self
171 .0
172 .get(&BuiltinName::add_mod)
173 .and_then(|pi| pi.first())
174 .cloned(),
175 mul_mod: self
176 .0
177 .get(&BuiltinName::mul_mod)
178 .and_then(|pi| pi.first())
179 .cloned(),
180 }
181 }
182}
183
184impl From<AirPrivateInputSerializable> for AirPrivateInput {
185 fn from(private_input: AirPrivateInputSerializable) -> Self {
186 let mut inputs = HashMap::new();
187 let mut insert_input = |input_name, input| {
188 if let Some(input) = input {
189 inputs.insert(input_name, input);
190 }
191 };
192 insert_input(BuiltinName::pedersen, private_input.pedersen);
193 insert_input(BuiltinName::range_check, private_input.range_check);
194 insert_input(BuiltinName::ecdsa, private_input.ecdsa);
195 insert_input(BuiltinName::bitwise, private_input.bitwise);
196 insert_input(BuiltinName::ec_op, private_input.ec_op);
197 insert_input(BuiltinName::keccak, private_input.keccak);
198 insert_input(BuiltinName::poseidon, private_input.poseidon);
199
200 Self(inputs)
201 }
202}
203
204impl AirPrivateInputSerializable {
205 pub fn serialize_json(&self) -> Result<String, serde_json::Error> {
206 serde_json::to_string_pretty(&self)
207 }
208}
209
210mod mod_input_instance_batch_serde {
211 use super::*;
212
213 use serde::{Deserializer, Serializer};
214
215 pub(crate) fn serialize<S: Serializer>(
216 value: &BTreeMap<usize, ModInputMemoryVars>,
217 s: S,
218 ) -> Result<S::Ok, S::Error> {
219 let value = value.iter().map(|v| v.1).collect::<Vec<_>>();
220
221 value.serialize(s)
222 }
223
224 pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
225 d: D,
226 ) -> Result<BTreeMap<usize, ModInputMemoryVars>, D::Error> {
227 let value = Vec::<ModInputMemoryVars>::deserialize(d)?;
228
229 Ok(value.into_iter().enumerate().collect())
230 }
231
232 #[cfg(feature = "std")]
233 #[test]
234 fn test_serde() {
235 let input_value = vec![
236 (
237 0,
238 ModInputMemoryVars {
239 a_offset: 5,
240 b_offset: 5,
241 c_offset: 5,
242 a0: Felt252::from(5u32),
243 a1: Felt252::from(5u32),
244 a2: Felt252::from(5u32),
245 a3: Felt252::from(5u32),
246 b0: Felt252::from(5u32),
247 b1: Felt252::from(5u32),
248 b2: Felt252::from(5u32),
249 b3: Felt252::from(5u32),
250 c0: Felt252::from(5u32),
251 c1: Felt252::from(5u32),
252 c2: Felt252::from(5u32),
253 c3: Felt252::from(5u32),
254 },
255 ),
256 (
257 1,
258 ModInputMemoryVars {
259 a_offset: 7,
260 b_offset: 7,
261 c_offset: 7,
262 a0: Felt252::from(7u32),
263 a1: Felt252::from(7u32),
264 a2: Felt252::from(7u32),
265 a3: Felt252::from(7u32),
266 b0: Felt252::from(7u32),
267 b1: Felt252::from(7u32),
268 b2: Felt252::from(7u32),
269 b3: Felt252::from(7u32),
270 c0: Felt252::from(7u32),
271 c1: Felt252::from(7u32),
272 c2: Felt252::from(7u32),
273 c3: Felt252::from(7u32),
274 },
275 ),
276 ]
277 .into_iter()
278 .collect::<BTreeMap<usize, _>>();
279
280 let bytes = Vec::new();
281 let mut serializer = serde_json::Serializer::new(bytes);
282 serialize(&input_value, &mut serializer).unwrap();
283 let bytes = serializer.into_inner();
284
285 let mut deserializer = serde_json::Deserializer::from_slice(&bytes);
286 let output_value = deserialize(&mut deserializer).unwrap();
287
288 assert_eq!(input_value, output_value);
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use crate::types::layout_name::LayoutName;
295 #[cfg(feature = "std")]
296 use {
297 super::*,
298 crate::air_private_input::{AirPrivateInput, AirPrivateInputSerializable},
299 assert_matches::assert_matches,
300 };
301
302 #[cfg(any(target_arch = "wasm32", not(feature = "std")))]
303 use crate::alloc::string::ToString;
304
305 #[cfg(feature = "std")]
306 #[test]
307 fn test_from_serializable() {
308 let serializable_private_input = AirPrivateInputSerializable {
309 trace_path: "trace.bin".to_string(),
310 memory_path: "memory.bin".to_string(),
311 pedersen: Some(vec![PrivateInput::Pair(PrivateInputPair {
312 index: 0,
313 x: Felt252::from(100),
314 y: Felt252::from(200),
315 })]),
316 range_check: Some(vec![PrivateInput::Value(PrivateInputValue {
317 index: 10000,
318 value: Felt252::from(8000),
319 })]),
320 range_check96: Some(vec![PrivateInput::Value(PrivateInputValue {
321 index: 10000,
322 value: Felt252::from(8000),
323 })]),
324 ecdsa: Some(vec![PrivateInput::Signature(PrivateInputSignature {
325 index: 0,
326 pubkey: Felt252::from(123),
327 msg: Felt252::from(456),
328 signature_input: SignatureInput {
329 r: Felt252::from(654),
330 w: Felt252::from(321),
331 },
332 })]),
333 bitwise: Some(vec![PrivateInput::Pair(PrivateInputPair {
334 index: 4,
335 x: Felt252::from(7),
336 y: Felt252::from(8),
337 })]),
338 ec_op: Some(vec![PrivateInput::EcOp(PrivateInputEcOp {
339 index: 1,
340 p_x: Felt252::from(10),
341 p_y: Felt252::from(10),
342 m: Felt252::from(100),
343 q_x: Felt252::from(11),
344 q_y: Felt252::from(14),
345 })]),
346 keccak: Some(vec![PrivateInput::KeccakState(PrivateInputKeccakState {
347 index: 0,
348 input_s0: Felt252::from(0),
349 input_s1: Felt252::from(1),
350 input_s2: Felt252::from(2),
351 input_s3: Felt252::from(3),
352 input_s4: Felt252::from(4),
353 input_s5: Felt252::from(5),
354 input_s6: Felt252::from(6),
355 input_s7: Felt252::from(7),
356 })]),
357 poseidon: Some(vec![PrivateInput::PoseidonState(
358 PrivateInputPoseidonState {
359 index: 42,
360 input_s0: Felt252::from(1),
361 input_s1: Felt252::from(2),
362 input_s2: Felt252::from(3),
363 },
364 )]),
365 add_mod: None,
366 mul_mod: None,
367 };
368
369 let private_input = AirPrivateInput::from(serializable_private_input.clone());
370
371 assert_matches!(private_input.0.get(&BuiltinName::pedersen), data if data == serializable_private_input.pedersen.as_ref());
372 assert_matches!(private_input.0.get(&BuiltinName::range_check), data if data == serializable_private_input.range_check.as_ref());
373 assert_matches!(private_input.0.get(&BuiltinName::ecdsa), data if data == serializable_private_input.ecdsa.as_ref());
374 assert_matches!(private_input.0.get(&BuiltinName::bitwise), data if data == serializable_private_input.bitwise.as_ref());
375 assert_matches!(private_input.0.get(&BuiltinName::ec_op), data if data == serializable_private_input.ec_op.as_ref());
376 assert_matches!(private_input.0.get(&BuiltinName::keccak), data if data == serializable_private_input.keccak.as_ref());
377 assert_matches!(private_input.0.get(&BuiltinName::poseidon), data if data == serializable_private_input.poseidon.as_ref());
378 }
379
380 #[test]
381 fn serialize_air_private_input_small_layout_only_builtins() {
382 let config = crate::cairo_run::CairoRunConfig {
383 proof_mode: true,
384 relocate_mem: true,
385 trace_enabled: true,
386 layout: LayoutName::small,
387 ..Default::default()
388 };
389 let runner = crate::cairo_run::cairo_run(include_bytes!("../../cairo_programs/proof_programs/fibonacci.json"), &config, &mut crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor::new_empty()).unwrap();
390 let public_input = runner.get_air_private_input();
391 let serialized_public_input =
392 public_input.to_serializable("/dev/null".to_string(), "/dev/null".to_string());
393 assert!(serialized_public_input.pedersen.is_some());
394 assert!(serialized_public_input.range_check.is_some());
395 assert!(serialized_public_input.ecdsa.is_some());
396 assert!(serialized_public_input.bitwise.is_none());
397 assert!(serialized_public_input.ec_op.is_none());
398 assert!(serialized_public_input.keccak.is_none());
399 assert!(serialized_public_input.poseidon.is_none());
400 }
401}