Skip to main content

arcis_interface/
json.rs

1use crate::types::{CircuitInterface, ScalarKind, Value};
2use serde::{
3    de::{self, MapAccess, Visitor},
4    Deserialize,
5    Deserializer,
6    Serialize,
7};
8use serde_json::{json, Value as JsonValue};
9use std::fmt;
10
11#[derive(Serialize, Deserialize, Debug)]
12pub struct ManticoreInterface {
13    pub inputs: Vec<String>,
14    pub outputs: Vec<String>,
15}
16
17impl ManticoreInterface {
18    pub fn new(inputs: Vec<String>, outputs: Vec<String>) -> Self {
19        Self { inputs, outputs }
20    }
21
22    pub fn serialize(&self) -> Result<String, serde_json::Error> {
23        serde_json::to_string(self)
24    }
25
26    pub fn from_json(input: &str) -> Result<Self, serde_json::Error> {
27        serde_json::from_str(input)
28    }
29}
30
31impl<'de> Deserialize<'de> for CircuitInterface {
32    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33    where
34        D: Deserializer<'de>,
35    {
36        enum Field {
37            Name,
38            Inputs,
39            Outputs,
40        }
41
42        impl<'de> Deserialize<'de> for Field {
43            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
44            where
45                D: Deserializer<'de>,
46            {
47                struct FieldVisitor;
48
49                impl Visitor<'_> for FieldVisitor {
50                    type Value = Field;
51
52                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53                        formatter.write_str("`name`, `inputs`, or `outputs`")
54                    }
55
56                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
57                    where
58                        E: de::Error,
59                    {
60                        match value {
61                            "name" => Ok(Field::Name),
62                            "inputs" => Ok(Field::Inputs),
63                            "outputs" => Ok(Field::Outputs),
64                            _ => Err(de::Error::unknown_field(value, FIELDS)),
65                        }
66                    }
67                }
68
69                deserializer.deserialize_identifier(FieldVisitor)
70            }
71        }
72
73        struct CircuitInterfaceVisitor;
74
75        impl<'de> Visitor<'de> for CircuitInterfaceVisitor {
76            type Value = CircuitInterface;
77
78            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79                formatter.write_str("struct CircuitInterface")
80            }
81
82            fn visit_map<V>(self, mut map: V) -> Result<CircuitInterface, V::Error>
83            where
84                V: MapAccess<'de>,
85            {
86                let mut name = None;
87                let mut inputs = None;
88                let mut outputs = None;
89
90                while let Some(key) = map.next_key()? {
91                    match key {
92                        Field::Name => {
93                            if name.is_some() {
94                                return Err(de::Error::duplicate_field("name"));
95                            }
96                            name = Some(map.next_value()?);
97                        }
98                        Field::Inputs => {
99                            if inputs.is_some() {
100                                return Err(de::Error::duplicate_field("inputs"));
101                            }
102                            inputs = Some(map.next_value()?);
103                        }
104                        Field::Outputs => {
105                            if outputs.is_some() {
106                                return Err(de::Error::duplicate_field("outputs"));
107                            }
108                            outputs = Some(map.next_value()?);
109                        }
110                    }
111                }
112
113                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
114                let inputs = inputs.ok_or_else(|| de::Error::missing_field("inputs"))?;
115                let outputs = outputs.ok_or_else(|| de::Error::missing_field("output"))?;
116
117                Ok(CircuitInterface {
118                    name,
119                    inputs,
120                    outputs,
121                })
122            }
123        }
124
125        const FIELDS: &[&str] = &["name", "inputs", "outputs"];
126        deserializer.deserialize_struct("CircuitInterface", FIELDS, CircuitInterfaceVisitor)
127    }
128}
129
130impl Value {
131    /// Maps scalar size and kind to JSON type name.
132    ///
133    /// Returns standard Rust type names for common sizes (e.g., "u32", "i64"),
134    /// or generic names for non-standard sizes ("scalar" for unsigned, "signed_integer" for
135    /// signed).
136    fn get_scalar_type_name(size_in_bits: usize, kind: ScalarKind) -> &'static str {
137        match kind {
138            ScalarKind::Unsigned => match size_in_bits {
139                8 => "u8",
140                16 => "u16",
141                32 => "u32",
142                64 => "u64",
143                128 => "u128",
144                _ => "scalar",
145            },
146            ScalarKind::Signed => match size_in_bits {
147                8 => "i8",
148                16 => "i16",
149                32 => "i32",
150                64 => "i64",
151                128 => "i128",
152                _ => "signed_integer",
153            },
154        }
155    }
156}
157
158impl Serialize for Value {
159    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160    where
161        S: serde::Serializer,
162    {
163        let json_value = match self {
164            Value::MScalar { size_in_bits } => json!({
165                "type": "mscalar",
166                "size_in_bits": size_in_bits
167            }),
168            Value::MFloat { size_in_bits } => json!({
169                "type": "mfloat",
170                "size_in_bits": size_in_bits
171            }),
172            Value::MBool => json!({
173                "type": "mbool"
174            }),
175            Value::Scalar { size_in_bits, kind } => json!({
176                "type": Value::get_scalar_type_name(*size_in_bits, *kind),
177                "size_in_bits": size_in_bits
178            }),
179            Value::Float { size_in_bits } => json!({
180                "type": "float",
181                "size_in_bits": size_in_bits
182            }),
183            Value::Bool => json!({
184                "type": "bool"
185            }),
186            Value::Ciphertext { size_in_bits } => json!({
187                "type": "ciphertext",
188                "size_in_bits": size_in_bits
189            }),
190            Value::ArcisX25519Pubkey => json!({
191                "type": "arcis_x25519_pubkey",
192            }),
193            Value::Point => json!({
194                "type": "point"
195            }),
196            Value::UnsynchronizedBools { count } => json!({
197                "type": "unsynchronized_bools",
198                "count": count
199            }),
200            Value::AesCiphertextByte => json!({
201                "type": "aes_ciphertext_byte"
202            }),
203            Value::Array(vec) => json!({
204                "type": "array",
205                "content": vec
206            }),
207            Value::Tuple(vec) => json!({
208                "type": "tuple",
209                "content": vec
210            }),
211            Value::Struct(vec) => json!({
212                "type": "struct",
213                "content": vec
214            }),
215        };
216        json_value.serialize(serializer)
217    }
218}
219
220impl<'de> Deserialize<'de> for Value {
221    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222    where
223        D: serde::Deserializer<'de>,
224    {
225        let json_value = JsonValue::deserialize(deserializer)?;
226
227        match json_value {
228            JsonValue::Object(map) => {
229                let type_ = map
230                    .get("type")
231                    .and_then(JsonValue::as_str)
232                    .ok_or_else(|| serde::de::Error::missing_field("type"))?;
233
234                match type_ {
235                    "mscalar" => {
236                        let size_in_bits = map
237                            .get("size_in_bits")
238                            .and_then(JsonValue::as_u64)
239                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
240                        Ok(Value::MScalar {
241                            size_in_bits: size_in_bits as usize,
242                        })
243                    }
244                    "mfloat" => {
245                        let size_in_bits = map
246                            .get("size_in_bits")
247                            .and_then(JsonValue::as_u64)
248                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
249                        Ok(Value::MFloat {
250                            size_in_bits: size_in_bits as usize,
251                        })
252                    }
253                    "mbool" => Ok(Value::MBool),
254                    "u8" => Ok(Value::Scalar {
255                        size_in_bits: 8,
256                        kind: ScalarKind::Unsigned,
257                    }),
258                    "u16" => Ok(Value::Scalar {
259                        size_in_bits: 16,
260                        kind: ScalarKind::Unsigned,
261                    }),
262                    "u32" => Ok(Value::Scalar {
263                        size_in_bits: 32,
264                        kind: ScalarKind::Unsigned,
265                    }),
266                    "u64" => Ok(Value::Scalar {
267                        size_in_bits: 64,
268                        kind: ScalarKind::Unsigned,
269                    }),
270                    "u128" => Ok(Value::Scalar {
271                        size_in_bits: 128,
272                        kind: ScalarKind::Unsigned,
273                    }),
274                    "i8" => Ok(Value::Scalar {
275                        size_in_bits: 8,
276                        kind: ScalarKind::Signed,
277                    }),
278                    "i16" => Ok(Value::Scalar {
279                        size_in_bits: 16,
280                        kind: ScalarKind::Signed,
281                    }),
282                    "i32" => Ok(Value::Scalar {
283                        size_in_bits: 32,
284                        kind: ScalarKind::Signed,
285                    }),
286                    "i64" => Ok(Value::Scalar {
287                        size_in_bits: 64,
288                        kind: ScalarKind::Signed,
289                    }),
290                    "i128" => Ok(Value::Scalar {
291                        size_in_bits: 128,
292                        kind: ScalarKind::Signed,
293                    }),
294                    "scalar" => {
295                        let size_in_bits = map
296                            .get("size_in_bits")
297                            .and_then(JsonValue::as_u64)
298                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
299                        Ok(Value::Scalar {
300                            size_in_bits: size_in_bits as usize,
301                            kind: ScalarKind::Unsigned,
302                        })
303                    }
304                    "signed_integer" => {
305                        let size_in_bits = map
306                            .get("size_in_bits")
307                            .and_then(JsonValue::as_u64)
308                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
309                        Ok(Value::Scalar {
310                            size_in_bits: size_in_bits as usize,
311                            kind: ScalarKind::Signed,
312                        })
313                    }
314                    "ciphertext" => {
315                        let size_in_bits = map
316                            .get("size_in_bits")
317                            .and_then(JsonValue::as_u64)
318                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
319                        Ok(Value::Ciphertext {
320                            size_in_bits: size_in_bits as usize,
321                        })
322                    }
323                    "arcis_x25519_pubkey" => Ok(Value::ArcisX25519Pubkey),
324                    "point" => Ok(Value::Point),
325                    "unsynchronized_bools" => {
326                        let count = map
327                            .get("count")
328                            .and_then(JsonValue::as_u64)
329                            .ok_or_else(|| serde::de::Error::missing_field("count"))?;
330                        Ok(Value::UnsynchronizedBools {
331                            count: count as usize,
332                        })
333                    }
334                    "float" => {
335                        let size_in_bits = map
336                            .get("size_in_bits")
337                            .and_then(JsonValue::as_u64)
338                            .ok_or_else(|| serde::de::Error::missing_field("size_in_bits"))?;
339                        Ok(Value::Float {
340                            size_in_bits: size_in_bits as usize,
341                        })
342                    }
343                    "bool" => Ok(Value::Bool),
344                    "aes_ciphertext_byte" => Ok(Value::AesCiphertextByte),
345                    "array" | "tuple" | "struct" => {
346                        let content = map
347                            .get("content")
348                            .ok_or_else(|| serde::de::Error::missing_field("content"))?;
349                        let vec: Vec<Value> =
350                            serde_json::from_value(content.clone()).map_err(|e| {
351                                serde::de::Error::custom(format!(
352                                    "Failed to deserialize content: {}",
353                                    e
354                                ))
355                            })?;
356                        match type_ {
357                            "array" => Ok(Value::Array(vec)),
358                            "tuple" => Ok(Value::Tuple(vec)),
359                            "struct" => Ok(Value::Struct(vec)),
360                            _ => unreachable!(),
361                        }
362                    }
363                    _ => Err(serde::de::Error::unknown_variant(
364                        type_,
365                        &[
366                            "mscalar",
367                            "mfloat",
368                            "mbool",
369                            "u8",
370                            "u16",
371                            "u32",
372                            "u64",
373                            "u128",
374                            "i8",
375                            "i16",
376                            "i32",
377                            "i64",
378                            "i128",
379                            "scalar",
380                            "signed_integer",
381                            "float",
382                            "bool",
383                            "array",
384                            "tuple",
385                            "struct",
386                            "ciphertext",
387                            "arcis_x25519_pubkey",
388                            "point",
389                            "unsynchronized_bools",
390                            "aes_ciphertext_byte",
391                        ],
392                    )),
393                }
394            }
395            _ => Err(serde::de::Error::invalid_type(
396                serde::de::Unexpected::Other("non-object"),
397                &"object",
398            )),
399        }
400    }
401}
402
403#[cfg(test)]
404mod tests {
405    use super::*;
406    use serde_json::json;
407
408    #[test]
409    fn test_mscalar_serialization() {
410        let value = Value::MScalar { size_in_bits: 32 };
411        let serialized = serde_json::to_value(value).unwrap();
412        assert_eq!(
413            serialized,
414            json!({
415                "type": "mscalar",
416                "size_in_bits": 32
417            })
418        );
419    }
420
421    #[test]
422    fn test_unsynchronized_bools_round_trips() {
423        let value = Value::UnsynchronizedBools { count: 1568 };
424        let serialized = serde_json::to_value(value.clone()).unwrap();
425        assert_eq!(
426            serialized,
427            json!({
428                "type": "unsynchronized_bools",
429                "count": 1568
430            })
431        );
432        assert_eq!(serde_json::from_value::<Value>(serialized).unwrap(), value);
433    }
434
435    #[test]
436    fn test_aes_ciphertext_byte_round_trips() {
437        let value = Value::AesCiphertextByte;
438        let serialized = serde_json::to_value(value.clone()).unwrap();
439        assert_eq!(serialized, json!({ "type": "aes_ciphertext_byte" }));
440        assert_eq!(serde_json::from_value::<Value>(serialized).unwrap(), value);
441    }
442
443    /// It maps to a single on-chain parameter, however many bits it carries -- the property the
444    /// argument matcher relies on.
445    #[test]
446    fn test_unsynchronized_bools_is_one_value() {
447        assert_eq!(
448            Value::UnsynchronizedBools { count: 1568 }.size_in_scalars(),
449            1
450        );
451    }
452
453    #[test]
454    fn test_mbool_serialization() {
455        let value = Value::MBool;
456        let serialized = serde_json::to_value(value).unwrap();
457        assert_eq!(
458            serialized,
459            json!({
460                "type": "mbool"
461            })
462        );
463    }
464
465    #[test]
466    fn test_bool_serialization() {
467        let value = Value::Bool;
468        let serialized = serde_json::to_value(value).unwrap();
469        assert_eq!(
470            serialized,
471            json!({
472                "type": "bool"
473            })
474        );
475    }
476
477    #[test]
478    fn test_array_serialization() {
479        let value = Value::Array(vec![
480            Value::Scalar {
481                size_in_bits: 60,
482                kind: ScalarKind::Unsigned,
483            },
484            Value::Bool,
485        ]);
486        let serialized = serde_json::to_value(value).unwrap();
487        assert_eq!(
488            serialized,
489            json!({
490                "type": "array",
491                "content": [
492                    {
493                        "type": "scalar",
494                        "size_in_bits": 60
495                    },
496                    {
497                        "type": "bool"
498                    }
499                ]
500            })
501        );
502    }
503
504    #[test]
505    fn test_nested_structure_serialization() {
506        let value = Value::Struct(vec![
507            Value::Tuple(vec![Value::MScalar { size_in_bits: 32 }, Value::MBool]),
508            Value::Array(vec![
509                Value::Scalar {
510                    size_in_bits: 64,
511                    kind: ScalarKind::Unsigned,
512                },
513                Value::Bool,
514            ]),
515        ]);
516        let serialized = serde_json::to_string(&value).unwrap();
517        let deserialized: Value = serde_json::from_str(&serialized).unwrap();
518        assert_eq!(value, deserialized);
519    }
520
521    #[test]
522    fn test_mscalar_deserialization() {
523        let json = r#"{"type": "mscalar", "size_in_bits": 32}"#;
524        let deserialized: Value = serde_json::from_str(json).unwrap();
525        assert_eq!(deserialized, Value::MScalar { size_in_bits: 32 });
526    }
527
528    #[test]
529    fn test_array_deserialization() {
530        let json = r#"
531        {
532            "type": "array",
533            "content": [
534                {"type": "scalar", "size_in_bits": 64},
535                {"type": "bool"}
536            ]
537        }"#;
538        let deserialized: Value = serde_json::from_str(json).unwrap();
539        assert_eq!(
540            deserialized,
541            Value::Array(vec![
542                Value::Scalar {
543                    size_in_bits: 64,
544                    kind: ScalarKind::Unsigned,
545                },
546                Value::Bool,
547            ])
548        );
549    }
550
551    #[test]
552    fn test_invalid_type_deserialization() {
553        let json = r#"{"type": "invalid_type"}"#;
554        let result: Result<Value, _> = serde_json::from_str(json);
555        assert!(result.is_err());
556    }
557
558    #[test]
559    fn test_missing_size_in_bits_deserialization() {
560        let json = r#"{"type": "mscalar"}"#;
561        let result: Result<Value, _> = serde_json::from_str(json);
562        assert!(result.is_err());
563    }
564
565    #[test]
566    fn test_plaintext_type_serialization() {
567        // Test all standard numeric sizes (unsigned)
568        let test_cases = [
569            (
570                Value::Scalar {
571                    size_in_bits: 8,
572                    kind: ScalarKind::Unsigned,
573                },
574                "u8",
575            ),
576            (
577                Value::Scalar {
578                    size_in_bits: 16,
579                    kind: ScalarKind::Unsigned,
580                },
581                "u16",
582            ),
583            (
584                Value::Scalar {
585                    size_in_bits: 32,
586                    kind: ScalarKind::Unsigned,
587                },
588                "u32",
589            ),
590            (
591                Value::Scalar {
592                    size_in_bits: 64,
593                    kind: ScalarKind::Unsigned,
594                },
595                "u64",
596            ),
597            (
598                Value::Scalar {
599                    size_in_bits: 128,
600                    kind: ScalarKind::Unsigned,
601                },
602                "u128",
603            ),
604            // Test non-standard size falls back to scalar
605            (
606                Value::Scalar {
607                    size_in_bits: 24,
608                    kind: ScalarKind::Unsigned,
609                },
610                "scalar",
611            ),
612        ];
613
614        for (value, expected_type) in test_cases {
615            // Test serialization
616            let serialized = serde_json::to_value(&value).unwrap();
617            let expected = match &value {
618                Value::Scalar { size_in_bits, .. } => json!({
619                    "type": expected_type,
620                    "size_in_bits": size_in_bits
621                }),
622                Value::Bool => json!({
623                    "type": expected_type
624                }),
625                _ => unreachable!(),
626            };
627            assert_eq!(serialized, expected);
628
629            // Test deserialization
630            let json = serde_json::to_string(&expected).unwrap();
631            let deserialized: Value = serde_json::from_str(&json).unwrap();
632            assert_eq!(deserialized, value);
633        }
634    }
635
636    #[test]
637    fn test_signed_integer_serialization() {
638        let test_cases = [
639            (
640                Value::Scalar {
641                    size_in_bits: 8,
642                    kind: ScalarKind::Signed,
643                },
644                "i8",
645            ),
646            (
647                Value::Scalar {
648                    size_in_bits: 16,
649                    kind: ScalarKind::Signed,
650                },
651                "i16",
652            ),
653            (
654                Value::Scalar {
655                    size_in_bits: 32,
656                    kind: ScalarKind::Signed,
657                },
658                "i32",
659            ),
660            (
661                Value::Scalar {
662                    size_in_bits: 64,
663                    kind: ScalarKind::Signed,
664                },
665                "i64",
666            ),
667            (
668                Value::Scalar {
669                    size_in_bits: 128,
670                    kind: ScalarKind::Signed,
671                },
672                "i128",
673            ),
674            (
675                Value::Scalar {
676                    size_in_bits: 24,
677                    kind: ScalarKind::Signed,
678                },
679                "signed_integer",
680            ),
681        ];
682
683        for (value, expected_type) in test_cases {
684            // Test serialization
685            let serialized = serde_json::to_value(&value).unwrap();
686            let expected = json!({
687                "type": expected_type,
688                "size_in_bits": match &value {
689                    Value::Scalar { size_in_bits, .. } => size_in_bits,
690                    _ => unreachable!(),
691                }
692            });
693            assert_eq!(serialized, expected);
694
695            // Test deserialization
696            let json = serde_json::to_string(&expected).unwrap();
697            let deserialized: Value = serde_json::from_str(&json).unwrap();
698            assert_eq!(deserialized, value);
699        }
700    }
701
702    #[test]
703    fn test_backward_compatibility() {
704        // Test that old JSON without 'kind' field defaults to unsigned
705        let old_json_cases = [
706            (r#"{"type": "u8", "size_in_bits": 8}"#, 8),
707            (r#"{"type": "u16", "size_in_bits": 16}"#, 16),
708            (r#"{"type": "u32", "size_in_bits": 32}"#, 32),
709            (r#"{"type": "u64", "size_in_bits": 64}"#, 64),
710            (r#"{"type": "u128", "size_in_bits": 128}"#, 128),
711            (r#"{"type": "scalar", "size_in_bits": 24}"#, 24),
712        ];
713
714        for (json, expected_size) in old_json_cases {
715            let deserialized: Value = serde_json::from_str(json).unwrap();
716            assert_eq!(
717                deserialized,
718                Value::Scalar {
719                    size_in_bits: expected_size,
720                    kind: ScalarKind::Unsigned
721                }
722            );
723        }
724    }
725
726    #[test]
727    fn test_mixed_signed_unsigned_serialization() {
728        // Test that signed and unsigned integers serialize differently
729        let unsigned = Value::Scalar {
730            size_in_bits: 32,
731            kind: ScalarKind::Unsigned,
732        };
733        let signed = Value::Scalar {
734            size_in_bits: 32,
735            kind: ScalarKind::Signed,
736        };
737
738        let unsigned_json = serde_json::to_value(&unsigned).unwrap();
739        let signed_json = serde_json::to_value(&signed).unwrap();
740
741        assert_eq!(
742            unsigned_json,
743            json!({
744                "type": "u32",
745                "size_in_bits": 32
746            })
747        );
748        assert_eq!(
749            signed_json,
750            json!({
751                "type": "i32",
752                "size_in_bits": 32
753            })
754        );
755
756        // Ensure they're different
757        assert_ne!(unsigned_json, signed_json);
758    }
759}