Skip to main content

cairo_vm/
air_private_input.rs

1use std::collections::{BTreeMap, HashMap};
2
3use crate::types::builtin_name::BuiltinName;
4use serde::{Deserialize, Serialize};
5
6use crate::Felt252;
7
8// Serializable format, matches the file output of the python implementation
9#[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// Contains only builtin public inputs, useful for library users
36#[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}