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