Skip to main content

taceo_ark_serde_compat/
lib.rs

1#![cfg_attr(not(doctest), doc = include_str!("../README.md"))]
2#![deny(missing_docs)]
3#![deny(clippy::all, clippy::pedantic)]
4#![deny(
5    clippy::allow_attributes_without_reason,
6    clippy::assertions_on_result_states,
7    clippy::dbg_macro,
8    clippy::decimal_literal_representation,
9    clippy::exhaustive_enums,
10    clippy::iter_over_hash_type,
11    clippy::let_underscore_must_use,
12    clippy::missing_assert_message,
13    clippy::print_stderr,
14    clippy::print_stdout,
15    clippy::undocumented_unsafe_blocks,
16    clippy::unnecessary_safety_comment,
17    clippy::unwrap_used
18)]
19#![allow(
20    clippy::missing_errors_doc,
21    reason = "We allow missing error sections in this crate"
22)]
23#![allow(
24    clippy::needless_pass_by_value,
25    reason = "We want to consume most of the time as only internal helpers"
26)]
27#![allow(
28    clippy::doc_markdown,
29    reason = "We allow BabyJubJub to not be in backticks"
30)]
31
32use std::str::FromStr;
33use std::{fmt, marker::PhantomData};
34
35use ark_ec::{
36    AffineRepr, CurveGroup,
37    pairing::Pairing,
38    short_weierstrass::{Affine, Projective, SWCurveConfig},
39};
40use ark_ff::{
41    CubicExtConfig, CubicExtField, Field, Fp12Config, Fp12ConfigWrapper, PrimeField, QuadExtConfig,
42    QuadExtField, Zero,
43};
44use ark_serialize::{CanonicalDeserialize as _, CanonicalSerialize as _, Compress};
45use num_bigint::Sign;
46use serde::ser::Error;
47use serde::{
48    Serializer,
49    de::{self},
50    ser::SerializeSeq as _,
51};
52
53#[cfg(test)]
54mod test;
55
56#[cfg(any(feature = "bn254", feature = "bls12-381"))]
57mod impl_macro;
58
59/// Trait providing serialization for pairing-friendly elliptic curves.
60///
61/// This trait defines a standard interface for serializing and deserializing pairing curve
62/// elements (G1, G2, GT) to and from both human-readable and non-human readable formats.
63/// It is implemented for specific pairing curves like BN254 and BLS12-381.
64///
65/// For human-readable formats (JSON), the serialization uses decimal strings for field
66/// elements and arrays of strings for group elements to ensure compatibility with Circom
67/// and other tools. For non-human readable formats (bincode, CBOR), it uses `ark-serialize`
68/// with compressed mode.
69pub trait CanonicalJsonSerialize: Pairing {
70    /// Serializes a G1 affine point as an array of coordinate strings.
71    fn serialize_g1<S: Serializer>(p: &Self::G1Affine, ser: S) -> Result<S::Ok, S::Error>;
72
73    /// Serializes a G2 affine point as an array of coordinate strings.
74    fn serialize_g2<S: Serializer>(p: &Self::G2Affine, ser: S) -> Result<S::Ok, S::Error>;
75
76    /// Serializes a target group (GT) element as an array of coordinate strings.
77    fn serialize_gt<S: Serializer>(p: &Self::TargetField, ser: S) -> Result<S::Ok, S::Error>;
78
79    /// Serializes a sequence of G1 affine points as an array of coordinate arrays.
80    fn serialize_g1_seq<S: Serializer>(p: &[Self::G1Affine], ser: S) -> Result<S::Ok, S::Error>;
81
82    /// Deserializes a G1 affine point from coordinate strings with full validation.
83    fn deserialize_g1<'de, D>(deserializer: D) -> Result<Self::G1Affine, D::Error>
84    where
85        D: de::Deserializer<'de>;
86
87    /// Deserializes a G1 affine point from coordinate strings without validation checks.
88    ///
89    /// # Safety
90    ///
91    /// This skips curve and subgroup checks. Only use with trusted input.
92    fn deserialize_g1_unchecked<'de, D>(deserializer: D) -> Result<Self::G1Affine, D::Error>
93    where
94        D: de::Deserializer<'de>;
95
96    /// Deserializes a G2 affine point from coordinate strings with full validation.
97    fn deserialize_g2<'de, D>(deserializer: D) -> Result<Self::G2Affine, D::Error>
98    where
99        D: de::Deserializer<'de>;
100
101    /// Deserializes a G2 affine point from coordinate strings without validation checks.
102    ///
103    /// # Safety
104    ///
105    /// This skips curve and subgroup checks. Only use with trusted input.
106    fn deserialize_g2_unchecked<'de, D>(deserializer: D) -> Result<Self::G2Affine, D::Error>
107    where
108        D: de::Deserializer<'de>;
109
110    /// Deserializes a target group (GT) element from coordinate strings.
111    fn deserialize_gt<'de, D>(deserializer: D) -> Result<Self::TargetField, D::Error>
112    where
113        D: de::Deserializer<'de>;
114
115    /// Deserializes a sequence of G1 affine points from coordinate arrays with full validation.
116    fn deserialize_g1_seq<'de, D>(deserializer: D) -> Result<Vec<Self::G1Affine>, D::Error>
117    where
118        D: de::Deserializer<'de>;
119
120    /// Deserializes a sequence of G1 affine points from coordinate arrays without validation checks.
121    ///
122    /// # Safety
123    ///
124    /// This skips curve and subgroup checks for all points. Only use with trusted input.
125    fn deserialize_g1_seq_unchecked<'de, D>(
126        deserializer: D,
127    ) -> Result<Vec<Self::G1Affine>, D::Error>
128    where
129        D: de::Deserializer<'de>;
130}
131
132// Silence the error in case we use no features
133#[derive(Debug)]
134#[allow(unused, reason = "Can be unused if we turn of all features")]
135pub(crate) struct SerdeCompatError(&'static str);
136
137impl fmt::Display for SerdeCompatError {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.write_str(self.0)
140    }
141}
142
143/// Indicates whether we should check if deserialized are valid
144/// points on the curves.
145/// `No` indicates to skip those checks, which is by orders of magnitude
146/// faster, but could potentially result in undefined behaviour. Use
147/// only with care.
148#[derive(Debug, Clone, Copy)]
149#[allow(
150    clippy::exhaustive_enums,
151    reason = "Doesn't need to be exhaustive as this is binary"
152)]
153pub enum CheckElement {
154    /// Indicates to perform curve checks
155    Yes,
156    /// Indicates to skip curve checks
157    No,
158}
159
160/// Serialize a prime field element.
161///
162/// For human-readable formats (JSON), serializes as a decimal string.
163/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
164///
165/// # Example
166///
167/// ```ignore
168/// use serde::Serialize;
169/// use ark_bn254::Fr;
170///
171/// #[derive(Serialize)]
172/// struct MyStruct {
173///     #[serde(serialize_with = "taceo_ark_serde_compat::serialize_f")]
174///     field: Fr,
175/// }
176/// ```
177pub fn serialize_f<S: Serializer>(p: &impl PrimeField, ser: S) -> Result<S::Ok, S::Error> {
178    if ser.is_human_readable() {
179        ser.serialize_str(&p.to_string())
180    } else {
181        let mut bytes = Vec::with_capacity(p.serialized_size(Compress::Yes));
182        p.serialize_compressed(&mut bytes)
183            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
184        ser.serialize_bytes(&bytes)
185    }
186}
187
188/// Serialize a sequence of prime field elements.
189///
190/// For human-readable formats (JSON), serializes as an array of decimal strings.
191/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
192///
193/// # Example
194///
195/// ```ignore
196/// use serde::Serialize;
197/// use ark_bn254::Fr;
198///
199/// #[derive(Serialize)]
200/// struct MyStruct {
201///     #[serde(serialize_with = "taceo_ark_serde_compat::serialize_f_seq")]
202///     fields: Vec<Fr>,
203/// }
204/// ```
205pub fn serialize_f_seq<S: Serializer, F: PrimeField>(ps: &[F], ser: S) -> Result<S::Ok, S::Error> {
206    if ser.is_human_readable() {
207        let mut seq = ser.serialize_seq(Some(ps.len()))?;
208        for p in ps {
209            seq.serialize_element(&p.to_string())?;
210        }
211        seq.end()
212    } else {
213        let mut bytes = Vec::with_capacity(ps.serialized_size(Compress::Yes));
214        ps.serialize_compressed(&mut bytes)
215            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
216        ser.serialize_bytes(&bytes)
217    }
218}
219
220/// Deserialize a prime field element. Allows negative values and is consistent with Circom's negative value parsing. Will return an error if element is larger than modulus.
221///
222/// This adds malleability as (p-1) and 1 result in the same value due to the implementation of Circom, where a number (-x) is defined as p - x, where p is the modulus of the prime field.
223///
224/// For human-readable formats (JSON), deserializes from a decimal string.
225/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
226///
227/// # Example
228///
229/// ```ignore
230/// use serde::Deserialize;
231/// use ark_bn254::Fr;
232///
233/// #[derive(Deserialize)]
234/// struct MyStruct {
235///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f_signed")]
236///     field: Fr,
237/// }
238/// ```
239pub fn deserialize_f_signed<'de, F, D>(deserializer: D) -> Result<F, D::Error>
240where
241    D: de::Deserializer<'de>,
242    F: PrimeField,
243{
244    let visitor = PrimeFieldVisitor::<false, F>::default();
245    if deserializer.is_human_readable() {
246        deserializer.deserialize_str(visitor)
247    } else {
248        deserializer.deserialize_bytes(visitor)
249    }
250}
251
252/// Deserialize an unsigned prime field element. Returns an error if the value is negative or larger than modulus.
253///
254/// For human-readable formats (JSON), deserializes from a decimal string.
255/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
256///
257/// # Example
258///
259/// ```ignore
260/// use serde::Deserialize;
261/// use ark_bn254::Fr;
262///
263/// #[derive(Deserialize)]
264/// struct MyStruct {
265///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f")]
266///     field: Fr,
267/// }
268/// ```
269pub fn deserialize_f<'de, F, D>(deserializer: D) -> Result<F, D::Error>
270where
271    D: de::Deserializer<'de>,
272    F: PrimeField,
273{
274    let visitor = PrimeFieldVisitor::<true, F>::default();
275    if deserializer.is_human_readable() {
276        deserializer.deserialize_str(visitor)
277    } else {
278        deserializer.deserialize_bytes(visitor)
279    }
280}
281
282/// Deserialize a sequence of prime field elements.
283///
284/// For human-readable formats (JSON), deserializes from an array of decimal strings.
285/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
286///
287/// # Example
288///
289/// ```ignore
290/// use serde::Deserialize;
291/// use ark_bn254::Fr;
292///
293/// #[derive(Deserialize)]
294/// struct MyStruct {
295///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f_seq")]
296///     fields: Vec<Fr>,
297/// }
298/// ```
299pub fn deserialize_f_seq<'de, D, F>(deserializer: D) -> Result<Vec<F>, D::Error>
300where
301    D: de::Deserializer<'de>,
302    F: PrimeField,
303{
304    let visitor = PrimeFieldSeqVisitor::<true, F> {
305        phantom_data: PhantomData,
306        size: None,
307    };
308    deser_seq_or_bytes(deserializer, visitor)
309}
310
311/// Deserialize a sequence of prime field elements. Allows negative values and is consistent with Circom's negative value parsing. Will return an error if element is larger than modulus.
312///
313/// This adds malleability as (p-1) and 1 result in the same value due to the implementation of Circom, where a number (-x) is defined as p - x, where p is the modulus of the prime field.
314///
315///
316/// For human-readable formats (JSON), deserializes from an array of decimal strings.
317/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
318///
319/// # Example
320///
321/// ```ignore
322/// use serde::Deserialize;
323/// use ark_bn254::Fr;
324///
325/// #[derive(Deserialize)]
326/// struct MyStruct {
327///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f_seq_signed")]
328///     fields: Vec<Fr>,
329/// }
330/// ```
331pub fn deserialize_f_seq_signed<'de, D, F>(deserializer: D) -> Result<Vec<F>, D::Error>
332where
333    D: de::Deserializer<'de>,
334    F: PrimeField,
335{
336    let visitor = PrimeFieldSeqVisitor::<false, F> {
337        phantom_data: PhantomData,
338        size: None,
339    };
340    deser_seq_or_bytes(deserializer, visitor)
341}
342
343/// Deserialize a fixed-size array of prime field elements.
344///
345/// For human-readable formats (JSON), deserializes from an array of decimal strings.
346/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
347/// Returns an error if the sequence does not contain exactly `LENGTH` elements.
348///
349/// # Example
350///
351/// ```ignore
352/// use serde::Deserialize;
353/// use ark_bn254::Fr;
354///
355/// #[derive(Deserialize)]
356/// struct MyStruct {
357///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f_array")]
358///     fields: [Fr; 4],
359/// }
360/// ```
361pub fn deserialize_f_array<'de, const LENGTH: usize, D, F>(
362    deserializer: D,
363) -> Result<[F; LENGTH], D::Error>
364where
365    D: de::Deserializer<'de>,
366    F: PrimeField,
367{
368    let visitor = PrimeFieldSeqVisitor::<true, F> {
369        phantom_data: PhantomData,
370        size: Some(LENGTH),
371    };
372    deser_array(deserializer, visitor)
373}
374
375/// Deserialize a fixed-size array of prime field elements. Allows negative values and is consistent with Circom's negative value parsing. Will return an error if element is larger than modulus.
376///
377/// This adds malleability as (p-1) and 1 result in the same value due to the implementation of Circom, where a number (-x) is defined as p - x, where p is the modulus of the prime field.
378///
379/// For human-readable formats (JSON), deserializes from an array of decimal strings.
380/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
381/// Returns an error if the sequence does not contain exactly `LENGTH` elements.
382///
383/// # Example
384///
385/// ```ignore
386/// use serde::Deserialize;
387/// use ark_bn254::Fr;
388///
389/// #[derive(Deserialize)]
390/// struct MyStruct {
391///     #[serde(deserialize_with = "taceo_ark_serde_compat::deserialize_f_array_signed")]
392///     fields: [Fr; 4],
393/// }
394/// ```
395pub fn deserialize_f_array_signed<'de, const LENGTH: usize, D, F>(
396    deserializer: D,
397) -> Result<[F; LENGTH], D::Error>
398where
399    D: de::Deserializer<'de>,
400    F: PrimeField,
401{
402    let visitor = PrimeFieldSeqVisitor::<false, F> {
403        phantom_data: PhantomData,
404        size: Some(LENGTH),
405    };
406    deser_array(deserializer, visitor)
407}
408
409/// Serialize a G1 affine point.
410///
411/// For human-readable formats (JSON), serializes as an array of three projective coordinate
412/// strings `[x, y, z]`. The point at infinity is represented as `["0", "1", "0"]`.
413/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
414///
415/// This is a generic function that works with any curve implementing `AffineRepr`.
416/// For curve-specific helpers, see the module functions like `bn254::serialize_g1`.
417pub fn serialize_g1<S: Serializer, F: Field>(
418    p: &impl AffineRepr<BaseField = F>,
419    ser: S,
420) -> Result<S::Ok, S::Error> {
421    if ser.is_human_readable() {
422        let strings = g1_to_strings_projective(p);
423        let mut seq = ser.serialize_seq(Some(strings.len()))?;
424        for ele in strings {
425            seq.serialize_element(&ele)?;
426        }
427        seq.end()
428    } else {
429        let mut bytes = Vec::with_capacity(p.serialized_size(Compress::Yes));
430        p.serialize_compressed(&mut bytes)
431            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
432        ser.serialize_bytes(&bytes)
433    }
434}
435
436/// Serialize a G2 affine point.
437///
438/// For human-readable formats (JSON), serializes as a 3×2 array of projective coordinate
439/// strings `[[x0, x1], [y0, y1], [z0, z1]]`, where each coordinate is represented as a
440/// quadratic extension field element (two components). The point at infinity is represented
441/// as `[["0", "0"], ["1", "0"], ["0", "0"]]`.
442/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
443///
444/// This is a generic function that works with any curve implementing `AffineRepr` with
445/// a quadratic extension base field. For curve-specific helpers, see the module functions
446/// like `bn254::serialize_g2`.
447pub fn serialize_g2<F, S: Serializer>(
448    p: &impl AffineRepr<BaseField = QuadExtField<F>>,
449    ser: S,
450) -> Result<S::Ok, S::Error>
451where
452    F: QuadExtConfig,
453{
454    if ser.is_human_readable() {
455        let mut x_seq = ser.serialize_seq(Some(3))?;
456        let (x, y) = p
457            .xy()
458            .unwrap_or((QuadExtField::<F>::zero(), QuadExtField::<F>::zero()));
459        x_seq.serialize_element(&[x.c0.to_string(), x.c1.to_string()])?;
460        x_seq.serialize_element(&[y.c0.to_string(), y.c1.to_string()])?;
461        x_seq.serialize_element(&["1", "0"])?;
462        x_seq.end()
463    } else {
464        let mut bytes = Vec::with_capacity(p.serialized_size(Compress::Yes));
465        p.serialize_compressed(&mut bytes)
466            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
467        ser.serialize_bytes(&bytes)
468    }
469}
470
471/// Serialize a target group (GT/Fq12) element.
472///
473/// For human-readable formats (JSON), serializes as a 2×3×2 array of decimal strings.
474/// An Fq12 element is viewed as two Fq6 components, each containing three Fq2 components,
475/// where each Fq2 is a pair of base field elements. The resulting structure is
476/// `[[[a00, a01], [a10, a11], [a20, a21]], [[b00, b01], [b10, b11], [b20, b21]]]`,
477/// where each innermost pair represents an Fq2 element as decimal strings.
478/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
479///
480/// This is a generic function. For curve-specific helpers, see the module functions
481/// like `bn254::serialize_gt`.
482pub fn serialize_gt<S: Serializer, T>(
483    p: &QuadExtField<Fp12ConfigWrapper<T>>,
484    ser: S,
485) -> Result<S::Ok, S::Error>
486where
487    T: Fp12Config,
488{
489    if ser.is_human_readable() {
490        let a = p.c0;
491        let b = p.c1;
492        let aa = a.c0;
493        let ab = a.c1;
494        let ac = a.c2;
495        let ba = b.c0;
496        let bb = b.c1;
497        let bc = b.c2;
498        let a = [
499            [aa.c0.to_string(), aa.c1.to_string()],
500            [ab.c0.to_string(), ab.c1.to_string()],
501            [ac.c0.to_string(), ac.c1.to_string()],
502        ];
503        let b = [
504            [ba.c0.to_string(), ba.c1.to_string()],
505            [bb.c0.to_string(), bb.c1.to_string()],
506            [bc.c0.to_string(), bc.c1.to_string()],
507        ];
508        let mut seq = ser.serialize_seq(Some(2))?;
509        seq.serialize_element(&a)?;
510        seq.serialize_element(&b)?;
511        seq.end()
512    } else {
513        let mut bytes = Vec::with_capacity(p.serialized_size(Compress::Yes));
514        p.serialize_compressed(&mut bytes)
515            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
516        ser.serialize_bytes(&bytes)
517    }
518}
519
520/// Serialize a sequence of G1 affine points.
521///
522/// For human-readable formats (JSON), serializes as an array of projective coordinate arrays
523/// where each point is represented as `[x, y, z]` with decimal strings. The point at infinity
524/// is represented as `["0", "1", "0"]`.
525/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
526///
527/// This is a generic function. For curve-specific helpers, see the module functions
528/// like `bn254::serialize_g1_seq`.
529pub fn serialize_g1_seq<S: Serializer, F: PrimeField>(
530    ps: &[impl AffineRepr<BaseField = F>],
531    ser: S,
532) -> Result<S::Ok, S::Error> {
533    if ser.is_human_readable() {
534        let mut seq = ser.serialize_seq(Some(ps.len()))?;
535        for p in ps {
536            seq.serialize_element(&g1_to_strings_projective(p))?;
537        }
538        seq.end()
539    } else {
540        let mut bytes = Vec::with_capacity(ps.serialized_size(Compress::Yes));
541        ps.serialize_compressed(&mut bytes)
542            .map_err(|_| S::Error::custom("cannot canonical serialize element"))?;
543        ser.serialize_bytes(&bytes)
544    }
545}
546
547/// Converts a G1 affine point to projective coordinate strings.
548///
549/// Returns `[x, y, "1"]` for finite points and `["0", "1", "0"]` for the point at infinity.
550fn g1_to_strings_projective(p: &impl AffineRepr) -> [String; 3] {
551    if let Some((x, y)) = p.xy() {
552        [x.to_string(), y.to_string(), "1".to_owned()]
553    } else {
554        //point at infinity
555        ["0".to_owned(), "1".to_owned(), "0".to_owned()]
556    }
557}
558
559/// Dispatches deserialization to `deserialize_seq` for human-readable formats and
560/// `deserialize_bytes` for non-human-readable formats.
561#[inline]
562pub(crate) fn deser_seq_or_bytes<'de, D, V>(
563    deserializer: D,
564    visitor: V,
565) -> Result<V::Value, D::Error>
566where
567    D: de::Deserializer<'de>,
568    V: de::Visitor<'de>,
569{
570    if deserializer.is_human_readable() {
571        deserializer.deserialize_seq(visitor)
572    } else {
573        deserializer.deserialize_bytes(visitor)
574    }
575}
576
577/// Dispatches deserialization and converts the resulting `Vec<T>` into a `[T; LENGTH]` array.
578///
579/// Returns an error if the deserialized length does not match `LENGTH`.
580#[inline]
581pub(crate) fn deser_array<'de, T, const LENGTH: usize, D, V>(
582    deserializer: D,
583    visitor: V,
584) -> Result<[T; LENGTH], D::Error>
585where
586    D: de::Deserializer<'de>,
587    V: de::Visitor<'de, Value = Vec<T>> + Clone,
588{
589    deser_seq_or_bytes(deserializer, visitor.clone())?
590        .try_into()
591        .map_err(|arr: Vec<_>| de::Error::invalid_length(arr.len(), &visitor))
592}
593
594#[derive(Default)]
595pub(crate) struct PrimeFieldVisitor<const UNSIGNED: bool, F> {
596    phantom_data: PhantomData<F>,
597}
598
599#[derive(Default, Clone)]
600pub(crate) struct PrimeFieldSeqVisitor<const UNSIGNED: bool, F> {
601    phantom_data: PhantomData<F>,
602    size: Option<usize>,
603}
604
605/// Deserialize a G1 affine point with full validation.
606///
607/// For human-readable formats (JSON), deserializes from `[x, y, z]` format as decimal strings.
608/// The point at infinity must be `["0", "1", "0"]`.
609/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
610/// Performs full validation including field element decoding, on-curve check, and
611/// subgroup membership verification.
612///
613/// This is a generic function. For curve-specific helpers, see the module functions
614/// like `bn254::deserialize_g1`.
615///
616/// # Errors
617///
618/// Returns an error if the coordinates are invalid, the point is not on the curve,
619/// or the point is not in the correct subgroup.
620pub fn deserialize_g1<'de, D, F, G1>(deserializer: D) -> Result<Affine<G1>, D::Error>
621where
622    D: de::Deserializer<'de>,
623    F: PrimeField,
624    G1: SWCurveConfig<BaseField = F>,
625{
626    let visitor = G1Visitor::<true, _, _>(PhantomData);
627    deser_seq_or_bytes(deserializer, visitor)
628}
629
630/// Deserialize a G1 affine point without validation.
631///
632/// For human-readable formats (JSON), deserializes from `[x, y, z]` format as decimal strings.
633/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
634/// **Does not** perform validation checks (field canonical form, on-curve, subgroup membership),
635/// making it significantly faster but potentially unsafe.
636///
637/// This is a generic function. For curve-specific helpers, see the module functions
638/// like `bn254::deserialize_g1_unchecked`.
639///
640/// # Safety
641///
642/// Only use this function with trusted input. Invalid points can lead to undefined
643/// behavior or security vulnerabilities in downstream cryptographic operations.
644pub fn deserialize_g1_unchecked<'de, D, F, G1>(deserializer: D) -> Result<Affine<G1>, D::Error>
645where
646    D: de::Deserializer<'de>,
647    F: PrimeField,
648    G1: SWCurveConfig<BaseField = F>,
649{
650    let visitor = G1Visitor::<false, _, _>(PhantomData);
651    deser_seq_or_bytes(deserializer, visitor)
652}
653
654/// Deserialize a G2 affine point with full validation.
655///
656/// For human-readable formats (JSON), deserializes from `[[x0, x1], [y0, y1], [z0, z1]]`
657/// format as decimal strings.
658/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
659/// Performs full validation including field element decoding, on-curve check, and
660/// subgroup membership verification.
661///
662/// This is a generic function. For curve-specific helpers, see the module functions
663/// like `bn254::deserialize_g2`.
664///
665/// # Errors
666///
667/// Returns an error if the coordinates are invalid, the point is not on the curve,
668/// or the point is not in the correct subgroup.
669pub fn deserialize_g2<'de, D, F, Q, G2>(deserializer: D) -> Result<Affine<G2>, D::Error>
670where
671    D: de::Deserializer<'de>,
672    F: PrimeField,
673    Q: QuadExtConfig<BaseField = F>,
674    G2: SWCurveConfig<BaseField = QuadExtField<Q>>,
675{
676    let visitor = G2Visitor::<true, _, _, _>(PhantomData);
677    deser_seq_or_bytes(deserializer, visitor)
678}
679
680/// Deserialize a G2 affine point without validation.
681///
682/// For human-readable formats (JSON), deserializes from `[[x0, x1], [y0, y1], [z0, z1]]`
683/// format as decimal strings.
684/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
685/// **Does not** perform validation checks (field canonical form, on-curve, subgroup membership),
686/// making it significantly faster but potentially unsafe.
687///
688/// This is a generic function. For curve-specific helpers, see the module functions
689/// like `bn254::deserialize_g2_unchecked`.
690///
691/// # Safety
692///
693/// Only use this function with trusted input. Invalid points can lead to undefined
694/// behavior or security vulnerabilities in downstream cryptographic operations.
695pub fn deserialize_g2_unchecked<'de, D, F, Q, G2>(deserializer: D) -> Result<Affine<G2>, D::Error>
696where
697    D: de::Deserializer<'de>,
698    F: PrimeField,
699    Q: QuadExtConfig<BaseField = F>,
700    G2: SWCurveConfig<BaseField = QuadExtField<Q>>,
701{
702    let visitor = G2Visitor::<false, _, _, _>(PhantomData);
703    deser_seq_or_bytes(deserializer, visitor)
704}
705/// Deserialize a target group (GT/Fq12) element.
706///
707/// For human-readable formats (JSON), deserializes from the nested array structure
708/// `[[[a00, a01], [a10, a11], [a20, a21]], [[b00, b01], [b10, b11], [b20, b21]]]`.
709/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
710/// Performs full validation of all component field elements.
711///
712/// This is a generic function. For curve-specific helpers, see the module functions
713/// like `bn254::deserialize_gt`.
714///
715/// # Errors
716///
717/// Returns an error if the structure is invalid or any field element cannot be parsed.
718pub fn deserialize_gt<'de, D, F, Fp2, Fp6, Fp12>(
719    deserializer: D,
720) -> Result<QuadExtField<Fp12>, D::Error>
721where
722    D: de::Deserializer<'de>,
723    F: PrimeField,
724    Fp2: QuadExtConfig<BaseField = F>,
725    Fp6: CubicExtConfig<BaseField = QuadExtField<Fp2>>,
726    Fp12: QuadExtConfig<BaseField = CubicExtField<Fp6>>,
727{
728    let visitor = GtVisitor(PhantomData);
729    deser_seq_or_bytes(deserializer, visitor)
730}
731
732/// Deserialize a sequence of G1 affine points with full validation.
733///
734/// For human-readable formats (JSON), deserializes from an array of G1 points where each
735/// point is in `[x, y, z]` projective format as decimal strings.
736/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
737/// Performs full validation for each point including field element decoding, on-curve check,
738/// and subgroup membership verification.
739///
740/// This is a generic function. For curve-specific helpers, see the module functions
741/// like `bn254::deserialize_g1_seq`.
742///
743/// # Errors
744///
745/// Returns an error if any coordinate is invalid, any point is not on the curve,
746/// or any point is not in the correct subgroup.
747pub fn deserialize_g1_seq<'de, D, F, G1>(deserializer: D) -> Result<Vec<Affine<G1>>, D::Error>
748where
749    D: de::Deserializer<'de>,
750    F: PrimeField,
751    G1: SWCurveConfig<BaseField = F>,
752{
753    let visitor = G1SeqVisitor::<true, _, _>(PhantomData);
754    deser_seq_or_bytes(deserializer, visitor)
755}
756
757/// Deserialize a sequence of G1 affine points without validation.
758///
759/// For human-readable formats (JSON), deserializes from an array of G1 points where each
760/// point is in `[x, y, z]` projective format as decimal strings.
761/// For non-human readable formats (bincode, CBOR), uses `ark-serialize` with compressed mode.
762/// **Does not** perform validation checks for any point, making it significantly faster but
763/// potentially unsafe.
764///
765/// This is a generic function. For curve-specific helpers, see the module functions
766/// like `bn254::deserialize_g1_seq_unchecked`.
767///
768/// # Safety
769///
770/// Only use this function with trusted input. Invalid points can lead to undefined
771/// behavior or security vulnerabilities in downstream cryptographic operations.
772pub fn deserialize_g1_seq_unchecked<'de, D, F, G1>(
773    deserializer: D,
774) -> Result<Vec<Affine<G1>>, D::Error>
775where
776    D: de::Deserializer<'de>,
777    F: PrimeField,
778    G1: SWCurveConfig<BaseField = F>,
779{
780    let visitor = G1SeqVisitor::<false, _, _>(PhantomData);
781    deser_seq_or_bytes(deserializer, visitor)
782}
783
784impl<'de, const CHECK: bool, G1, F> de::Visitor<'de> for G1Visitor<CHECK, F, G1>
785where
786    F: PrimeField,
787    G1: SWCurveConfig<BaseField = F>,
788{
789    type Value = Affine<G1>;
790
791    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
792        formatter.write_str("a sequence of 3 strings, representing a projective point on G1")
793    }
794
795    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
796    where
797        E: de::Error,
798    {
799        if CHECK {
800            Self::Value::deserialize_compressed(v)
801        } else {
802            Self::Value::deserialize_compressed_unchecked(v)
803        }
804        .map_err(|err| de::Error::custom(err.to_string()))
805    }
806
807    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
808    where
809        A: de::SeqAccess<'de>,
810    {
811        let x = seq.next_element::<String>()?.ok_or(de::Error::custom(
812            "expected G1 projective coordinates but x coordinate missing.".to_owned(),
813        ))?;
814        let y = seq.next_element::<String>()?.ok_or(de::Error::custom(
815            "expected G1 projective coordinates but y coordinate missing.".to_owned(),
816        ))?;
817        let z = seq.next_element::<String>()?.ok_or(de::Error::custom(
818            "expected G1 projective coordinates but z coordinate missing.".to_owned(),
819        ))?;
820        //check if there are no more elements
821        if seq.next_element::<String>()?.is_some() {
822            Err(de::Error::invalid_length(4, &self))
823        } else {
824            g1_from_strings_projective::<CHECK, _, _>(&x, &y, &z).map_err(de::Error::custom)
825        }
826    }
827}
828
829impl<'de, const CHECK: bool, F, Q, G2> de::Visitor<'de> for G2Visitor<CHECK, F, Q, G2>
830where
831    F: PrimeField,
832    Q: QuadExtConfig<BaseField = F>,
833    G2: SWCurveConfig<BaseField = QuadExtField<Q>>,
834{
835    type Value = Affine<G2>;
836
837    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
838        formatter
839            .write_str("a sequence of 3 sequences, representing a projective point on G2. The 3 sequences each consist of two strings")
840    }
841
842    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
843    where
844        E: de::Error,
845    {
846        if CHECK {
847            Self::Value::deserialize_compressed(v)
848        } else {
849            Self::Value::deserialize_compressed_unchecked(v)
850        }
851        .map_err(|err| de::Error::custom(err.to_string()))
852    }
853
854    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
855    where
856        A: de::SeqAccess<'de>,
857    {
858        let x = seq.next_element::<Vec<String>>()?.ok_or(de::Error::custom(
859            "expected G1 projective coordinates but x coordinate missing.".to_owned(),
860        ))?;
861        let y = seq.next_element::<Vec<String>>()?.ok_or(de::Error::custom(
862            "expected G2 projective coordinates but y coordinate missing.".to_owned(),
863        ))?;
864        let z = seq.next_element::<Vec<String>>()?.ok_or(de::Error::custom(
865            "expected G2 projective coordinates but z coordinate missing.".to_owned(),
866        ))?;
867        //check if there are no more elements
868        if seq.next_element::<String>()?.is_some() {
869            Err(de::Error::invalid_length(4, &self))
870        } else if x.len() != 2 {
871            Err(de::Error::custom(format!(
872                "x coordinates need two field elements for G2, but got {}",
873                x.len()
874            )))
875        } else if y.len() != 2 {
876            Err(de::Error::custom(format!(
877                "y coordinates need two field elements for G2, but got {}",
878                y.len()
879            )))
880        } else if z.len() != 2 {
881            Err(de::Error::custom(format!(
882                "z coordinates need two field elements for G2, but got {}",
883                z.len()
884            )))
885        } else {
886            g2_from_strings_projective::<CHECK, _, _, _>(&x[0], &x[1], &y[0], &y[1], &z[0], &z[1])
887                .map_err(de::Error::custom)
888        }
889    }
890}
891
892/// Parses a G1 affine point from projective coordinate strings.
893///
894/// If `CHECK` is true, validates the point is on the curve and in the correct subgroup.
895/// Always accepts the point at infinity without validation.
896fn g1_from_strings_projective<const CHECK: bool, F, G1>(
897    x: &str,
898    y: &str,
899    z: &str,
900) -> Result<Affine<G1>, SerdeCompatError>
901where
902    F: PrimeField,
903    G1: SWCurveConfig<BaseField = F>,
904{
905    let x = parse_field_str_inner_unsigned(x)?;
906    let y = parse_field_str_inner_unsigned(y)?;
907    let z = parse_field_str_inner_unsigned(z)?;
908    let p = Projective::<G1>::new_unchecked(x, y, z).into_affine();
909    if p.is_zero() {
910        return Ok(p);
911    }
912    if CHECK && !p.is_on_curve() {
913        return Err(SerdeCompatError("not con curve"));
914    }
915    if CHECK && !p.is_in_correct_subgroup_assuming_on_curve() {
916        return Err(SerdeCompatError("not in correct subgroup"));
917    }
918    Ok(p)
919}
920
921/// Parses a G2 affine point from projective coordinate strings.
922///
923/// Takes six strings representing the components of three Fq2 coordinates (x, y, z).
924/// If `CHECK` is true, validates the point is on the curve and in the correct subgroup.
925/// Always accepts the point at infinity without validation.
926fn g2_from_strings_projective<const CHECK: bool, F, Q, G2>(
927    x0: &str,
928    x1: &str,
929    y0: &str,
930    y1: &str,
931    z0: &str,
932    z1: &str,
933) -> Result<Affine<G2>, SerdeCompatError>
934where
935    F: PrimeField,
936    Q: QuadExtConfig<BaseField = F>,
937    G2: SWCurveConfig<BaseField = QuadExtField<Q>>,
938{
939    let x0 = parse_field_str_inner_unsigned(x0)?;
940    let x1 = parse_field_str_inner_unsigned(x1)?;
941    let y0 = parse_field_str_inner_unsigned(y0)?;
942    let y1 = parse_field_str_inner_unsigned(y1)?;
943    let z0 = parse_field_str_inner_unsigned(z0)?;
944    let z1 = parse_field_str_inner_unsigned(z1)?;
945
946    let x = QuadExtField::<Q>::new(x0, x1);
947    let y = QuadExtField::<Q>::new(y0, y1);
948    let z = QuadExtField::<Q>::new(z0, z1);
949    let p = Projective::<G2>::new_unchecked(x, y, z).into_affine();
950    if p.is_zero() {
951        return Ok(p);
952    }
953    if CHECK && !p.is_on_curve() {
954        return Err(SerdeCompatError("not on curve"));
955    }
956    if CHECK && !p.is_in_correct_subgroup_assuming_on_curve() {
957        return Err(SerdeCompatError("not on correct subgroup"));
958    }
959    Ok(p)
960}
961
962struct G1Visitor<const CHECK: bool, F, G1>(PhantomData<G1>)
963where
964    F: PrimeField,
965    G1: SWCurveConfig<BaseField = F>;
966
967struct G2Visitor<const CHECK: bool, F, Q, G2>(PhantomData<G2>)
968where
969    F: PrimeField,
970    Q: QuadExtConfig<BaseField = F>,
971    G2: SWCurveConfig<BaseField = QuadExtField<Q>>;
972
973struct GtVisitor<F, Fp2, Fp6, Fp12>(PhantomData<Fp12>)
974where
975    F: PrimeField,
976    Fp2: QuadExtConfig<BaseField = F>,
977    Fp6: CubicExtConfig<BaseField = QuadExtField<Fp2>>,
978    Fp12: QuadExtConfig<BaseField = CubicExtField<Fp6>>;
979
980struct G1SeqVisitor<const CHECK: bool, F, G1>(PhantomData<G1>)
981where
982    F: PrimeField,
983    G1: SWCurveConfig<BaseField = F>;
984
985impl<const UNSIGNED: bool, F: PrimeField> de::Visitor<'_> for PrimeFieldVisitor<UNSIGNED, F> {
986    type Value = F;
987
988    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
989        formatter.write_str(&format!(
990            "a string representing a field element in F_{}",
991            F::MODULUS
992        ))
993    }
994
995    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
996    where
997        E: de::Error,
998    {
999        Self::Value::deserialize_compressed(v).map_err(|err| de::Error::custom(err.to_string()))
1000    }
1001
1002    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1003    where
1004        E: de::Error,
1005    {
1006        parse_field_str_inner::<UNSIGNED, F>(v).map_err(E::custom)
1007    }
1008}
1009
1010impl<'de, const UNSIGNED: bool, F: PrimeField> de::Visitor<'de>
1011    for PrimeFieldSeqVisitor<UNSIGNED, F>
1012{
1013    type Value = Vec<F>;
1014
1015    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1016        if let Some(size) = self.size {
1017            formatter.write_str(&format!(
1018                "a sequence of strings representing field elements of length {size} in F_{}",
1019                F::MODULUS
1020            ))
1021        } else {
1022            formatter.write_str(&format!(
1023                "a sequence of strings representing field elements in F_{}",
1024                F::MODULUS
1025            ))
1026        }
1027    }
1028
1029    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
1030    where
1031        E: de::Error,
1032    {
1033        Self::Value::deserialize_compressed(v).map_err(|err| de::Error::custom(err.to_string()))
1034    }
1035
1036    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1037    where
1038        A: de::SeqAccess<'de>,
1039    {
1040        use serde::de::Error;
1041        let mut values = if let Some(size_hint) = seq.size_hint() {
1042            Vec::with_capacity(size_hint)
1043        } else {
1044            Vec::new()
1045        };
1046        while let Some(s) = seq.next_element::<String>()? {
1047            values.push(parse_field_str_inner::<UNSIGNED, F>(&s).map_err(A::Error::custom)?);
1048        }
1049        Ok(values)
1050    }
1051}
1052
1053impl<'de, F, Fp2, Fp6, Fp12> de::Visitor<'de> for GtVisitor<F, Fp2, Fp6, Fp12>
1054where
1055    F: PrimeField,
1056    Fp2: QuadExtConfig<BaseField = F>,
1057    Fp6: CubicExtConfig<BaseField = QuadExtField<Fp2>>,
1058    Fp12: QuadExtConfig<BaseField = CubicExtField<Fp6>>,
1059{
1060    type Value = QuadExtField<Fp12>;
1061
1062    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1063        formatter.write_str(
1064                "An element of Fp12 represented as string with radix 10. Must be a sequence of form [[[String; 2]; 3]; 2]."
1065            )
1066    }
1067
1068    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
1069    where
1070        E: de::Error,
1071    {
1072        Self::Value::deserialize_compressed(v).map_err(de::Error::custom)
1073    }
1074
1075    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1076    where
1077        A: de::SeqAccess<'de>,
1078    {
1079        let x = seq
1080            .next_element::<Vec<Vec<String>>>()?
1081            .ok_or(de::Error::custom(
1082                "expected elements target group in {} as sequence of sequences",
1083            ))?;
1084        let y = seq
1085            .next_element::<Vec<Vec<String>>>()?
1086            .ok_or(de::Error::custom(
1087                "expected elements target group in {} as sequence of sequences",
1088            ))?;
1089        if x.len() != 3 || y.len() != 3 {
1090            Err(de::Error::custom(
1091                "need three elements for cubic extension field in {}",
1092            ))
1093        } else {
1094            let c0 = cubic_extension_field_from_vec(x).map_err(de::Error::custom)?;
1095            let c1 = cubic_extension_field_from_vec(y).map_err(de::Error::custom)?;
1096            Ok(QuadExtField::new(c0, c1))
1097        }
1098    }
1099}
1100
1101/// Constructs a cubic extension field element from a nested vector of strings.
1102///
1103/// Expects a vector of three vectors, each containing two strings representing
1104/// an Fq2 element. Returns an Fq6 element.
1105#[inline]
1106fn cubic_extension_field_from_vec<F, Fp2, Fp6>(
1107    strings: Vec<Vec<String>>,
1108) -> Result<CubicExtField<Fp6>, SerdeCompatError>
1109where
1110    F: PrimeField,
1111    Fp2: QuadExtConfig<BaseField = F>,
1112    Fp6: CubicExtConfig<BaseField = QuadExtField<Fp2>>,
1113{
1114    if strings.len() == 3 {
1115        let c0 = quadratic_extension_field_from_vec(&strings[0])?;
1116        let c1 = quadratic_extension_field_from_vec(&strings[1])?;
1117        let c2 = quadratic_extension_field_from_vec(&strings[2])?;
1118        Ok(CubicExtField::new(c0, c1, c2))
1119    } else {
1120        Err(SerdeCompatError("expected cubic extension field"))
1121    }
1122}
1123
1124/// Constructs a quadratic extension field element from a slice of strings.
1125///
1126/// Expects exactly two strings representing the two components of an Fq2 element.
1127#[inline]
1128fn quadratic_extension_field_from_vec<F, Fp2>(
1129    strings: &[String],
1130) -> Result<QuadExtField<Fp2>, SerdeCompatError>
1131where
1132    F: PrimeField,
1133    Fp2: QuadExtConfig<BaseField = F>,
1134{
1135    if strings.len() == 2 {
1136        let c0 = parse_field_str_inner_unsigned(&strings[0])?;
1137        let c1 = parse_field_str_inner_unsigned(&strings[1])?;
1138        Ok(QuadExtField::new(c0, c1))
1139    } else {
1140        Err(SerdeCompatError("expected quadratic extension field"))
1141    }
1142}
1143
1144impl<'de, const CHECK: bool, F, G1> de::Visitor<'de> for G1SeqVisitor<CHECK, F, G1>
1145where
1146    F: PrimeField,
1147    G1: SWCurveConfig<BaseField = F>,
1148{
1149    type Value = Vec<Affine<G1>>;
1150
1151    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1152        formatter.write_str(
1153            "a sequence of elements representing projective points on G1, which in turn are sequences of three elements on the BaseField of the Curve.",
1154        )
1155    }
1156
1157    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
1158    where
1159        E: de::Error,
1160    {
1161        if CHECK {
1162            Self::Value::deserialize_compressed(v)
1163        } else {
1164            Self::Value::deserialize_compressed_unchecked(v)
1165        }
1166        .map_err(|err| de::Error::custom(err.to_string()))
1167    }
1168
1169    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1170    where
1171        A: de::SeqAccess<'de>,
1172    {
1173        let mut values = vec![];
1174        while let Some(point) = seq.next_element::<Vec<String>>()? {
1175            //check if there are no more elements
1176            if point.len() == 3 {
1177                values.push(
1178                    g1_from_strings_projective::<CHECK, _, _>(&point[0], &point[1], &point[2])
1179                        .map_err(|_| {
1180                            de::Error::custom("Invalid projective point on G1.".to_owned())
1181                        })?,
1182                );
1183            } else {
1184                return Err(de::Error::invalid_length(point.len(), &self));
1185            }
1186        }
1187        Ok(values)
1188    }
1189}
1190
1191#[inline]
1192fn parse_field_str_inner<const UNSIGNED: bool, F: PrimeField>(
1193    v: &str,
1194) -> Result<F, SerdeCompatError> {
1195    if UNSIGNED && v.starts_with('-') {
1196        return Err(SerdeCompatError("only expects positive numbers"));
1197    }
1198    if UNSIGNED {
1199        if v.chars().any(|x| !x.is_ascii_digit()) {
1200            return Err(SerdeCompatError("only expects digits 0-9 for numbers"));
1201        }
1202    } else if v
1203        .strip_prefix('-')
1204        .unwrap_or(v)
1205        .chars()
1206        .any(|x| !x.is_ascii_digit())
1207    {
1208        return Err(SerdeCompatError("only expects digits 0-9 for numbers"));
1209    }
1210    // need to do this double hop because BigInteger trait only has try_from for BigUint. Also we now do this conversion for every time we call this function, which is not super nice, but this also happens when using from_str as well
1211    let modulus =
1212        num_bigint::BigInt::from(num_bigint::BigUint::try_from(F::MODULUS).map_err(|_| {
1213            SerdeCompatError(
1214                "Cannot modulus of this prime field to BigUint - prime field not supported",
1215            )
1216        })?);
1217    let mut number =
1218        num_bigint::BigInt::from_str(v).map_err(|_| SerdeCompatError("invalid data"))?;
1219    if number.is_zero() && v != "0" {
1220        return Err(SerdeCompatError("zero must be serialized as '0'"));
1221    }
1222    if v.starts_with('0') && !number.is_zero() {
1223        return Err(SerdeCompatError("invalid leading zeros for number"));
1224    }
1225    if !UNSIGNED && number.sign() == Sign::Minus {
1226        if !number.is_zero() && v.starts_with("-0") {
1227            return Err(SerdeCompatError(
1228                "invalid leading zeros for negative number",
1229            ));
1230        }
1231        // We are in the sign case and the value is negative - to be compatible with Circom we add the modulus.
1232        number += modulus;
1233        // If the number is still negative, the value is larger than the Modulus. We reject this here. This allows us to call BigUint::try_from afterwards, as we know for sure the value is positive.
1234        if number.sign() == Sign::Minus {
1235            return Err(SerdeCompatError("doesn't fit into field"));
1236        }
1237    } else if UNSIGNED && number.sign() == Sign::Minus {
1238        return Err(SerdeCompatError("only expects positive numbers"));
1239    } else if modulus <= number {
1240        return Err(SerdeCompatError("doesn't fit into field"));
1241    }
1242    let number = num_bigint::BigUint::try_from(number).expect("Works due to checks above");
1243    // this should never happen for the fields we implement
1244    let number = F::BigInt::try_from(number)
1245        .map_err(|()| SerdeCompatError("Cannot convert to underlying BigInt again"))?;
1246    Ok(F::from_bigint(number).expect("Is some due to checks above"))
1247}
1248
1249#[inline]
1250fn parse_field_str_inner_unsigned<F: PrimeField>(v: &str) -> Result<F, SerdeCompatError> {
1251    parse_field_str_inner::<true, F>(v)
1252}
1253
1254#[cfg(feature = "bn254")]
1255impl_macro::impl_json_canonical!(ark_bn254, Bn254, bn254);
1256
1257#[cfg(feature = "bls12-381")]
1258impl_macro::impl_json_canonical!(ark_bls12_381, Bls12_381, bls12_381);
1259
1260#[cfg(feature = "babyjubjub")]
1261pub mod babyjubjub;