Skip to main content

taceo_circom_types/
lib.rs

1#![warn(missing_docs)]
2//! Types and utilities for reading Circom-generated files into arkworks representations.
3//!
4//! This crate provides deserialization support for Circom's binary and JSON formats,
5//! including proofs, verification keys, witnesses, R1CS constraint systems, and zkeys
6//! for both Groth16 and PLONK proof systems.
7#[cfg(all(feature = "zkey", any(feature = "groth16", feature = "plonk")))]
8mod binfile;
9#[cfg(feature = "groth16")]
10pub mod groth16;
11#[cfg(feature = "plonk")]
12pub mod plonk;
13
14#[cfg(feature = "r1cs")]
15mod r1cs;
16pub mod traits;
17
18#[cfg(feature = "witness")]
19mod witness;
20
21#[cfg(feature = "r1cs")]
22pub use r1cs::R1CS;
23#[cfg(feature = "r1cs")]
24pub use r1cs::R1CSParserError;
25
26#[cfg(feature = "witness")]
27pub use witness::Witness;
28#[cfg(feature = "witness")]
29pub use witness::WitnessParserError;
30
31#[cfg(all(feature = "zkey", any(feature = "groth16", feature = "plonk")))]
32pub use binfile::ZkeyParserError;
33
34pub use ark_serde_compat::CheckElement;
35
36// re-export ark_bn254
37#[cfg(feature = "bn254")]
38pub use ark_bn254;
39
40// re-export ark_bls12_381
41#[cfg(feature = "bls12-381")]
42pub use ark_bls12_381;
43
44#[cfg(any(feature = "r1cs", feature = "witness"))]
45pub(crate) mod reader_utils {
46    use ark_ff::PrimeField;
47    use ark_serialize::Read;
48    use std::{io, str::Utf8Error};
49    use thiserror::Error;
50
51    /// Error type describing errors during reading Circom file headers
52    #[derive(Debug, Error)]
53    pub enum InvalidHeaderError {
54        /// Error during IO operations (reading/opening file, etc.)
55        #[error(transparent)]
56        IoError(#[from] std::io::Error),
57        /// File header is not valid UTF-8
58        #[error(transparent)]
59        Utf8Error(#[from] Utf8Error),
60        /// File header does not match the expected header
61        #[error("Wrong header. Expected {0} but got {1}")]
62        WrongHeader(String, String),
63    }
64
65    pub(crate) fn read_header<R: Read>(
66        mut reader: R,
67        should_header: &str,
68    ) -> Result<(), InvalidHeaderError> {
69        let mut buf = [0_u8; 4];
70        reader.read_exact(&mut buf)?;
71        let is_header = std::str::from_utf8(&buf[..])?;
72        if is_header == should_header {
73            Ok(())
74        } else {
75            Err(InvalidHeaderError::WrongHeader(
76                should_header.to_owned(),
77                is_header.to_owned(),
78            ))
79        }
80    }
81
82    pub(crate) fn prime_field_from_reader<F: PrimeField>(
83        mut reader: impl Read,
84        size: usize,
85    ) -> io::Result<F> {
86        let mut buf = vec![0u8; size];
87        reader.read_exact(&mut buf[..])?;
88        Ok(F::from_le_bytes_mod_order(&buf))
89    }
90
91    // pub(crate) fn from_reader_for_groth16_zkey(reader: impl Read) -> SerResult<Self> {
92    //     Ok(Self::new_unchecked(
93    //         Self::montgomery_bigint_from_reader(reader)?.into_bigint(),
94    //     ))
95    // }
96}
97
98#[cfg(test)]
99pub(crate) mod tests {
100    // allow the tests folder to be unused in case we turn off the features
101    #![allow(unused)]
102    use std::path::PathBuf;
103
104    #[cfg(feature = "bn254")]
105    pub(crate) fn groth16_bn254_kats() -> PathBuf {
106        let cargo_manifest = PathBuf::from(std::env!("CARGO_MANIFEST_DIR"));
107        cargo_manifest.join("kats/groth16/bn254")
108    }
109
110    #[cfg(feature = "bn254")]
111    pub(crate) fn plonk_bn254_kats() -> PathBuf {
112        let cargo_manifest = PathBuf::from(std::env!("CARGO_MANIFEST_DIR"));
113        cargo_manifest.join("kats/plonk/bn254")
114    }
115
116    #[cfg(feature = "bls12-381")]
117    pub(crate) fn groth16_bls12_381_kats() -> PathBuf {
118        let cargo_manifest = PathBuf::from(std::env!("CARGO_MANIFEST_DIR"));
119        cargo_manifest.join("kats/groth16/bls12_381")
120    }
121
122    #[cfg(feature = "bls12-381")]
123    pub(crate) fn plonk_bls12_381_kats() -> PathBuf {
124        let cargo_manifest = PathBuf::from(std::env!("CARGO_MANIFEST_DIR"));
125        cargo_manifest.join("kats/plonk/bls12_381")
126    }
127}
128
129#[cfg(test)]
130pub(crate) mod test_utils {
131    #![allow(unused)]
132    #[cfg(feature = "bls12-381")]
133    macro_rules! to_g1_bls12_381 {
134        ($x: expr, $y: expr) => {{
135            use ark_ec::pairing::Pairing;
136            use std::str::FromStr;
137            <ark_bls12_381::Bls12_381 as Pairing>::G1Affine::new(
138                ark_bls12_381::Fq::from_str($x).unwrap(),
139                ark_bls12_381::Fq::from_str($y).unwrap(),
140            )
141        }};
142    }
143    #[cfg(feature = "bls12-381")]
144    macro_rules! to_g2_bls12_381 {
145        ({$x1: expr, $x2: expr}, {$y1: expr, $y2: expr}) => {{
146            use ark_ec::pairing::Pairing;
147            use std::str::FromStr;
148            <ark_bls12_381::Bls12_381 as Pairing>::G2Affine::new(
149                ark_bls12_381::Fq2::new(
150                    ark_bls12_381::Fq::from_str($x1).unwrap(),
151                    ark_bls12_381::Fq::from_str($x2).unwrap(),
152                ),
153                ark_bls12_381::Fq2::new(
154                    ark_bls12_381::Fq::from_str($y1).unwrap(),
155                    ark_bls12_381::Fq::from_str($y2).unwrap(),
156                ),
157            )
158        }};
159    }
160
161    #[cfg(feature = "bn254")]
162    macro_rules! to_g1_bn254 {
163        ($x: expr, $y: expr) => {{
164            use ark_ec::pairing::Pairing;
165            use std::str::FromStr;
166            <ark_bn254::Bn254 as Pairing>::G1Affine::new(
167                ark_bn254::Fq::from_str($x).unwrap(),
168                ark_bn254::Fq::from_str($y).unwrap(),
169            )
170        }};
171    }
172
173    #[cfg(feature = "bn254")]
174    macro_rules! to_g2_bn254 {
175        ({$x1: expr, $x2: expr}, {$y1: expr, $y2: expr}) => {{
176            use ark_ec::pairing::Pairing;
177            use std::str::FromStr;
178            <ark_bn254::Bn254 as Pairing>::G2Affine::new(
179                ark_bn254::Fq2::new(
180                    ark_bn254::Fq::from_str($x1).unwrap(),
181                    ark_bn254::Fq::from_str($x2).unwrap(),
182                ),
183                ark_bn254::Fq2::new(
184                    ark_bn254::Fq::from_str($y1).unwrap(),
185                    ark_bn254::Fq::from_str($y2).unwrap(),
186                ),
187            )
188        }};
189    }
190    #[cfg(feature = "bls12-381")]
191    pub(crate) use to_g1_bls12_381;
192    #[cfg(feature = "bn254")]
193    pub(crate) use to_g1_bn254;
194    #[cfg(feature = "bls12-381")]
195    pub(crate) use to_g2_bls12_381;
196    #[cfg(feature = "bn254")]
197    pub(crate) use to_g2_bn254;
198}