diff --git a/Cargo.lock b/Cargo.lock index aeddbb278..97e8b2b2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,7 +143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -798,7 +798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "bitvec", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -811,7 +811,7 @@ dependencies = [ "halo2_proofs", "itertools 0.13.0", "plonkish_backend", - "rand", + "rand 0.8.5", "serde", "thiserror 1.0.69", ] @@ -1008,6 +1008,40 @@ dependencies = [ "slab", ] +[[package]] +name = "garaga-calldata-tests" +version = "0.1.0" +dependencies = [ + "garaga_rs", + "num-bigint", + "serde", + "serde_json", + "thiserror 2.0.12", +] + +[[package]] +name = "garaga_rs" +version = "1.1.0" +source = "git+https://github.com/keep-starknet-strange/garaga?tag=v1.1.0#307c00af4a7f08653123d1ec9a6edae81f288260" +dependencies = [ + "arbitrary", + "getrandom 0.3.2", + "hex", + "itertools 0.14.0", + "lambdaworks-crypto", + "lambdaworks-math 0.11.0", + "lazy_static", + "num-bigint", + "num-integer", + "num-traits", + "rand 0.9.4", + "rayon", + "sha2", + "sha3 0.10.8", + "starknet-types-core", + "thiserror 2.0.12", +] + [[package]] name = "gemini-fibonacci" version = "0.1.0" @@ -1086,7 +1120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1119,8 +1153,8 @@ dependencies = [ "ff", "group", "halo2curves 0.3.3", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "rayon", "sha3 0.9.1", "tracing", @@ -1138,8 +1172,8 @@ dependencies = [ "num-traits", "pasta_curves", "paste", - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", "static_assertions", "subtle", ] @@ -1156,8 +1190,8 @@ dependencies = [ "num-traits", "pasta_curves", "paste", - "rand", - "rand_core", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "static_assertions", "subtle", @@ -1555,6 +1589,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -1590,6 +1633,39 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lambdaworks-crypto" +version = "0.11.0" +source = "git+https://github.com/lambdaclass/lambdaworks.git?rev=be4a329#be4a329dad5c847a37ab3831b6fdee546b2d0af9" +dependencies = [ + "lambdaworks-math 0.11.0", + "serde", + "sha2", + "sha3 0.10.8", +] + +[[package]] +name = "lambdaworks-math" +version = "0.11.0" +source = "git+https://github.com/lambdaclass/lambdaworks.git?rev=be4a329#be4a329dad5c847a37ab3831b6fdee546b2d0af9" +dependencies = [ + "rayon", + "serde", + "serde_json", +] + +[[package]] +name = "lambdaworks-math" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "018a95aa873eb49896a858dee0d925c33f3978d073c64b08dd4f2c9b35a017c6" +dependencies = [ + "getrandom 0.2.15", + "num-bigint", + "num-traits", + "rand 0.8.5", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1754,7 +1830,7 @@ dependencies = [ "getrandom 0.2.15", "hyperplonk-fibonacci", "plonk-fibonacci", - "rand", + "rand 0.8.5", "serde-wasm-bindgen", "thiserror 2.0.12", "toml 0.8.22", @@ -1950,7 +2026,7 @@ dependencies = [ "group", "hex", "lazy_static", - "rand", + "rand 0.8.5", "serde", "static_assertions", "subtle", @@ -2011,7 +2087,7 @@ dependencies = [ "fibonacci-circuit", "halo2_proofs", "plonkish_backend", - "rand", + "rand 0.8.5", "serde", ] @@ -2030,7 +2106,7 @@ dependencies = [ "num-integer", "pasta_curves", "poseidon", - "rand", + "rand 0.8.5", "rayon", "serde", "sha3 0.10.8", @@ -2103,8 +2179,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -2114,7 +2200,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -2126,6 +2222,15 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.2", +] + [[package]] name = "rayon" version = "1.10.0" @@ -2492,6 +2597,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.9.1" @@ -2590,6 +2706,19 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "starknet-types-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a12690813e587969cb4a9e7d8ebdb069d4bb7ec8d03275c5f719310c8e1f07c" +dependencies = [ + "generic-array", + "lambdaworks-math 0.13.0", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index ea2c85be7..8a69f4a3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["mopro-ffi", "cli", "tests"] +members = ["mopro-ffi", "cli", "tests", "garaga-calldata-tests"] resolver = "2" [workspace.dependencies] diff --git a/cli/src/init/circom.rs b/cli/src/init/circom.rs index f15b6ae94..a89584972 100644 --- a/cli/src/init/circom.rs +++ b/cli/src/init/circom.rs @@ -14,6 +14,9 @@ impl ProvingSystem for Circom { circom-prover = "0.1" rust-witness = "0.1" num-bigint = "0.4.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +garaga_rs = { git = "https://github.com/keep-starknet-strange/garaga", tag = "v1.1.0", package = "garaga_rs", optional = true } "#; const BUILD_DEPENDENCIES: &'static str = r#" witnesscalc-adapter = "0.1" @@ -21,7 +24,7 @@ rust-witness = "0.1" "#; const DEV_DEPENDENCIES: &'static str = r#" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.94" +serde_json = "1.0" "#; const BUILD_TEMPLATE: &'static str = r#" diff --git a/cli/src/init/write_toml.rs b/cli/src/init/write_toml.rs index 1a32d866c..fe9436fb7 100644 --- a/cli/src/init/write_toml.rs +++ b/cli/src/init/write_toml.rs @@ -14,6 +14,7 @@ default = ["uniffi"] uniffi = ["mopro-ffi/uniffi"] flutter = ["mopro-ffi/flutter"] wasm = ["mopro-ffi/wasm"] +garaga = ["garaga_rs"] [dependencies] mopro-ffi = { version = "=0.3.7" } diff --git a/cli/src/main.rs b/cli/src/main.rs index 530419914..2c0a4338b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -49,7 +49,6 @@ enum Commands { architectures: Option>, #[arg( long, - num_args = 1.., help = "Automatically run mopro update after build", conflicts_with = "no_auto_update" )] diff --git a/cli/src/template/circom/lib.rs b/cli/src/template/circom/lib.rs index cd0df22f6..e4422ef51 100644 --- a/cli/src/template/circom/lib.rs +++ b/cli/src/template/circom/lib.rs @@ -6,6 +6,8 @@ mod circom; pub use circom::{ generate_circom_proof, verify_circom_proof, CircomProof, CircomProofResult, ProofLib, G1, G2, }; +#[cfg(feature = "garaga")] +pub use circom::generate_circom_groth16_garaga_calldata; mod witness { rust_witness::witness!(multiplier2); diff --git a/cli/src/template/init/src/circom.rs b/cli/src/template/init/src/circom.rs index 624327839..3f9e9869f 100644 --- a/cli/src/template/init/src/circom.rs +++ b/cli/src/template/init/src/circom.rs @@ -1,3 +1,13 @@ +#[cfg(feature = "garaga")] +mod circom_garaga; +#[cfg(feature = "garaga")] +mod garaga_convert; +#[cfg(feature = "garaga")] +mod snarkjs_types; + +#[cfg(feature = "garaga")] +pub use circom_garaga::generate_circom_groth16_garaga_calldata; + use crate::MoproError; use circom_prover::{ prover::{ diff --git a/cli/src/template/init/src/circom/circom_garaga.rs b/cli/src/template/init/src/circom/circom_garaga.rs new file mode 100644 index 000000000..6a1d73c12 --- /dev/null +++ b/cli/src/template/init/src/circom/circom_garaga.rs @@ -0,0 +1,93 @@ +use super::garaga_convert::{to_groth16_proof_from_mopro, to_groth16_vk}; +use super::snarkjs_types::{parse_snarkjs_vk_json, GROTH16_PROTOCOL, SNARKJS_BN128_CURVE}; +use super::{CircomProof, CircomProofResult}; +use crate::MoproError; +use garaga_rs::calldata::full_proof_with_hints::groth16::{ + get_groth16_calldata_felt, Groth16Proof, Groth16VerificationKey, +}; +use garaga_rs::definitions::CurveID; + +fn garaga_calldata_core( + garaga_proof: Groth16Proof, + garaga_vk: Groth16VerificationKey, +) -> Result, MoproError> { + let felts = get_groth16_calldata_felt(&garaga_proof, &garaga_vk, CurveID::BN254) + .map_err(|e| MoproError::CircomError(format!("Garaga calldata error: {e}")))?; + + Ok(felts.into_iter().map(|f| f.to_string()).collect()) +} + +fn validate_public_input_count( + public_inputs: &[String], + n_public: usize, +) -> Result<(), MoproError> { + if public_inputs.len() != n_public { + return Err(MoproError::CircomError(format!( + "Garaga calldata error: public input count mismatch: got {}, nPublic {}", + public_inputs.len(), + n_public + ))); + } + Ok(()) +} + +fn validate_mopro_groth16_bn254(proof: &CircomProof) -> Result<(), String> { + if proof.protocol != GROTH16_PROTOCOL { + return Err(format!( + "unsupported proof protocol: {} (expected {GROTH16_PROTOCOL})", + proof.protocol + )); + } + let curve = proof.curve.to_ascii_lowercase(); + if curve != SNARKJS_BN128_CURVE && curve != "bn254" { + return Err(format!( + "unsupported curve: {} (BN254/{SNARKJS_BN128_CURVE} only in v1)", + proof.curve + )); + } + Ok(()) +} + +fn circom_proof_to_groth16( + proof: &CircomProof, + public_inputs: &[String], +) -> Result { + validate_mopro_groth16_bn254(proof)?; + to_groth16_proof_from_mopro( + &proof.a.x, + &proof.a.y, + &proof.b.x, + &proof.b.y, + &proof.c.x, + &proof.c.y, + public_inputs, + ) +} + +/// Build Starknet-compatible Groth16 calldata (BN254) from a [`CircomProofResult`]. +/// +/// Prove with [`super::generate_circom_proof`], then pass the result here together with +/// `verification_key_json` (contents of snarkjs `verification_key.json` from a one-time +/// zkey export). +/// +/// `proof_result.inputs` has the same content as SnarkJS `public.json` (decimal field +/// elements). No separate public-inputs file is required. +/// +/// Returns each Starknet felt as a decimal string, suitable for Flutter/Dart and +/// `starknet.dart` invoke calldata. Does not send transactions. +#[cfg_attr(feature = "uniffi", uniffi::export)] +pub fn generate_circom_groth16_garaga_calldata( + proof_result: CircomProofResult, + verification_key_json: String, +) -> Result, MoproError> { + let vk = parse_snarkjs_vk_json(&verification_key_json) + .map_err(|e| MoproError::CircomError(format!("Garaga calldata error: {e}")))?; + validate_public_input_count(&proof_result.inputs, vk.n_public)?; + + let garaga_proof = circom_proof_to_groth16(&proof_result.proof, &proof_result.inputs) + .map_err(|e| MoproError::CircomError(format!("Garaga calldata error: {e}")))?; + let garaga_vk = to_groth16_vk(&vk) + .map_err(|e| MoproError::CircomError(format!("Garaga calldata error: {e}")))?; + + garaga_calldata_core(garaga_proof, garaga_vk) +} diff --git a/cli/src/template/init/src/circom/garaga_convert.rs b/cli/src/template/init/src/circom/garaga_convert.rs new file mode 100644 index 000000000..f074e3ca4 --- /dev/null +++ b/cli/src/template/init/src/circom/garaga_convert.rs @@ -0,0 +1,111 @@ +use super::snarkjs_types::SnarkJsVerificationKey; +use garaga_rs::calldata::full_proof_with_hints::groth16::{Groth16Proof, Groth16VerificationKey}; +use garaga_rs::calldata::{G1PointBigUint, G2PointBigUint}; +use garaga_rs::definitions::{get_modulus_from_curve_id, CurveID}; +use num_bigint::BigUint; +use std::str::FromStr; +use std::sync::LazyLock; + +/// BN254 base-field modulus (Fq). Coordinates must be in `[0, p)`. +static BN254_BASE_FIELD: LazyLock = + LazyLock::new(|| get_modulus_from_curve_id(CurveID::BN254)); + +/// BN254 scalar-field order (Fr). Public inputs must be in `[0, n)`. +/// Same value as `BN254PrimeField::get_curve_params().n` in garaga_rs. +static BN254_SCALAR_FIELD: LazyLock = LazyLock::new(|| { + BigUint::parse_bytes( + b"30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000001", + 16, + ) + .expect("valid BN254 scalar-field hex") +}); + +/// Parse a decimal field element and require it to lie in the BN254 base field (Fq). +pub(crate) fn parse_biguint(s: &str) -> Result { + let value = BigUint::from_str(s).map_err(|e| format!("invalid coordinate '{s}': {e}"))?; + if value >= *BN254_BASE_FIELD { + return Err(format!("coordinate '{s}' is outside BN254 base field")); + } + Ok(value) +} + +fn parse_public_input_biguint(s: &str) -> Result { + let value = BigUint::from_str(s).map_err(|e| format!("invalid coordinate '{s}': {e}"))?; + if value >= *BN254_SCALAR_FIELD { + return Err(format!("public input '{s}' is outside BN254 scalar field")); + } + Ok(value) +} + +pub(crate) fn snarkjs_g1_to_garaga(coords: &[String]) -> Result { + if coords.len() < 2 { + return Err("G1 point must have at least two coordinates".to_string()); + } + Ok(G1PointBigUint { + x: parse_biguint(&coords[0])?, + y: parse_biguint(&coords[1])?, + }) +} + +/// SnarkJS G2 layout: `[[x0, x1], [y0, y1], [z0, z1]]` → Garaga `[x0, x1, y0, y1]`. +pub(crate) fn snarkjs_g2_to_garaga(rows: &[Vec]) -> Result { + if rows.len() < 2 || rows[0].len() < 2 || rows[1].len() < 2 { + return Err("G2 point must have two rows of two coordinates".to_string()); + } + Ok(G2PointBigUint { + x0: parse_biguint(&rows[0][0])?, + x1: parse_biguint(&rows[0][1])?, + y0: parse_biguint(&rows[1][0])?, + y1: parse_biguint(&rows[1][1])?, + }) +} + +pub(crate) fn public_inputs_to_biguint(public_inputs: &[String]) -> Result, String> { + public_inputs + .iter() + .map(|s| parse_public_input_biguint(s)) + .collect() +} + +pub(crate) fn mopro_g2_to_garaga(x: &[String], y: &[String]) -> Result { + if x.len() < 2 || y.len() < 2 { + return Err("G2 point must have two x and two y coordinates".to_string()); + } + Ok(G2PointBigUint { + x0: parse_biguint(&x[0])?, + x1: parse_biguint(&x[1])?, + y0: parse_biguint(&y[0])?, + y1: parse_biguint(&y[1])?, + }) +} + +pub(crate) fn to_groth16_proof_from_mopro( + a_x: &str, + a_y: &str, + b_x: &[String], + b_y: &[String], + c_x: &str, + c_y: &str, + public_inputs: &[String], +) -> Result { + Ok(Groth16Proof { + a: snarkjs_g1_to_garaga(&[a_x.to_string(), a_y.to_string()])?, + b: mopro_g2_to_garaga(b_x, b_y)?, + c: snarkjs_g1_to_garaga(&[c_x.to_string(), c_y.to_string()])?, + public_inputs: public_inputs_to_biguint(public_inputs)?, + image_id_journal_risc0: None, + vkey_public_values_sp1: None, + }) +} + +pub(crate) fn to_groth16_vk(vk: &SnarkJsVerificationKey) -> Result { + let mut values: Vec = Vec::new(); + values.extend(snarkjs_g1_to_garaga(&vk.vk_alpha_1)?.flatten()); + values.extend(snarkjs_g2_to_garaga(&vk.vk_beta_2)?.flatten()); + values.extend(snarkjs_g2_to_garaga(&vk.vk_gamma_2)?.flatten()); + values.extend(snarkjs_g2_to_garaga(&vk.vk_delta_2)?.flatten()); + for ic_point in &vk.ic { + values.extend(snarkjs_g1_to_garaga(ic_point)?.flatten()); + } + Ok(Groth16VerificationKey::from(values)) +} diff --git a/cli/src/template/init/src/circom/snarkjs_types.rs b/cli/src/template/init/src/circom/snarkjs_types.rs new file mode 100644 index 000000000..04e7a0ffc --- /dev/null +++ b/cli/src/template/init/src/circom/snarkjs_types.rs @@ -0,0 +1,48 @@ +use serde::Deserialize; + +#[derive(Debug, Clone, Deserialize)] +pub(crate) struct SnarkJsVerificationKey { + pub protocol: String, + pub curve: String, + #[serde(rename = "nPublic")] + pub n_public: usize, + pub vk_alpha_1: Vec, + pub vk_beta_2: Vec>, + pub vk_gamma_2: Vec>, + pub vk_delta_2: Vec>, + #[serde(rename = "IC")] + pub ic: Vec>, +} + +pub(crate) const SNARKJS_BN128_CURVE: &str = "bn128"; +pub(crate) const GROTH16_PROTOCOL: &str = "groth16"; + +pub(crate) fn parse_snarkjs_vk_json(s: &str) -> Result { + let vk: SnarkJsVerificationKey = + serde_json::from_str(s).map_err(|e| format!("invalid verification key JSON: {e}"))?; + validate_vk(&vk)?; + Ok(vk) +} + +fn validate_vk(vk: &SnarkJsVerificationKey) -> Result<(), String> { + if vk.protocol != GROTH16_PROTOCOL { + return Err(format!( + "unsupported vk protocol: {} (expected {GROTH16_PROTOCOL})", + vk.protocol + )); + } + if vk.curve != SNARKJS_BN128_CURVE { + return Err(format!( + "unsupported curve: {} (BN254/{SNARKJS_BN128_CURVE} only in v1)", + vk.curve + )); + } + if vk.ic.len() != vk.n_public + 1 { + return Err(format!( + "IC length mismatch: expected {} points (nPublic + 1), got {}", + vk.n_public + 1, + vk.ic.len() + )); + } + Ok(()) +} diff --git a/docs/docs/adapters/circom.md b/docs/docs/adapters/circom.md index 2ead42cce..473460926 100644 --- a/docs/docs/adapters/circom.md +++ b/docs/docs/adapters/circom.md @@ -329,6 +329,101 @@ let result = generate_circom_proof( ); ``` +## Starknet calldata (Garaga, optional) + +Mopro can format Circom Groth16 proofs as Starknet verifier calldata using +[Garaga v1.1.0](https://github.com/keep-starknet-strange/garaga/tree/v1.1.0). This is **calldata generation only** — +Mopro does not send transactions, manage accounts, estimate fees, or handle nonces. + +### Enable the feature + +The `garaga` feature and optional `garaga_rs` dependency are injected when you initialize a Circom project. Declaring them is not enough — you must turn the feature on for the target you build. + +```toml +[features] +default = ["uniffi"] +uniffi = ["mopro-ffi/uniffi"] +flutter = ["mopro-ffi/flutter"] +wasm = ["mopro-ffi/wasm"] +garaga = ["garaga_rs"] + +[dependencies] +garaga_rs = { git = "https://github.com/keep-starknet-strange/garaga", tag = "v1.1.0", package = "garaga_rs", optional = true } +``` + +Enable it for your bindings target: + +- **iOS / Android (UniFFI):** add `garaga` to `default`, e.g. `default = ["uniffi", "garaga"]`. +- **Flutter:** `mopro build` uses `--no-default-features --features flutter`, so `default` is ignored. Wire Garaga into the Flutter feature instead: + +```toml +flutter = ["mopro-ffi/flutter", "garaga"] +``` + +Then rebuild bindings so `generateCircomGroth16GaragaCalldata` is included. + +### Prepare verification key + +Export the verification key once from your zkey (same format snarkjs uses): + +```sh +snarkjs zkey export verificationkey circuit_final.zkey verification_key.json +``` + +### `generateCircomGroth16GaragaCalldata` + +Prove in-app with Mopro, then build Garaga calldata from the result. `CircomProofResult.inputs` +is a `Vec` with the same content as SnarkJS `public.json` — no separate public-inputs +file is required. The only required file input is `verification_key.json`. + +```rust +let result = generate_circom_proof( + zkey_path, + circuit_inputs, + ProofLib::Arkworks, +)?; + +let calldata = generate_circom_groth16_garaga_calldata( + result, + std::fs::read_to_string("verification_key.json")?, +)?; +// calldata: Vec — decimal Starknet felts for Garaga BN254 verifier +``` + +On mobile bindings, pass the `CircomProofResult` returned by `generateCircomProof` directly — +`inputs` is already available as a string list. + +**BN254 only** (`curve: "bn128"` / `"bn254"`). The on-chain verifier contract must be generated with Garaga v1.1.0 (`garaga gen`). + +### Flutter / `starknet.dart` + +Pass the returned strings to your Starknet client — Mopro stops at calldata formatting: + +```dart +final proofResult = await generateCircomProof( + zkeyPath: zkeyPath, + circuitInputs: circuitInputs, + proofLib: ProofLib.arkworks, +); + +// Contents of snarkjs verification_key.json (asset / file / network). +final vkJson = await rootBundle.loadString('assets/verification_key.json'); + +final calldata = await generateCircomGroth16GaragaCalldata( + proofResult: proofResult, + verificationKeyJson: vkJson, +); + +// Invoke your Garaga Groth16 verifier contract outside Mopro, e.g. with starknet.dart: +// await provider.invoke( +// contractAddress: verifierAddress, +// entrypoint: 'verify_groth16_proof_bn254', +// calldata: calldata.map((s) => BigInt.parse(s)).toList(), +// ); +``` + +Use your preferred Starknet account/wallet layer (`starknet.dart`, AVNU, etc.) for signing, submission, and RPC. + ## Using the Library After you have specified the circuits you want to use, you can follow the usual steps to build the library and use it in your project. diff --git a/garaga-calldata-tests/Cargo.toml b/garaga-calldata-tests/Cargo.toml new file mode 100644 index 000000000..946193842 --- /dev/null +++ b/garaga-calldata-tests/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "garaga-calldata-tests" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/lib.rs" + +[dependencies] +garaga_rs = { git = "https://github.com/keep-starknet-strange/garaga", tag = "v1.1.0", package = "garaga_rs" } +num-bigint = "0.4" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +thiserror = "2.0" + +[[bin]] +name = "gen-garaga-calldata-fixture" +path = "src/bin/gen_garaga_calldata_fixture.rs" diff --git a/garaga-calldata-tests/build.rs b/garaga-calldata-tests/build.rs new file mode 100644 index 000000000..d563fbaf8 --- /dev/null +++ b/garaga-calldata-tests/build.rs @@ -0,0 +1,6 @@ +fn main() { + // Template sources use `cfg(feature = "uniffi")` but this crate has no such + // Cargo feature (a real `uniffi = []` would break `--all-features`). Tell + // rustc the value is expected so check-cfg stays quiet. + println!("cargo::rustc-check-cfg=cfg(feature, values(\"uniffi\"))"); +} diff --git a/garaga-calldata-tests/fixtures/bn254/README.md b/garaga-calldata-tests/fixtures/bn254/README.md new file mode 100644 index 000000000..162429b38 --- /dev/null +++ b/garaga-calldata-tests/fixtures/bn254/README.md @@ -0,0 +1,19 @@ +# BN254 Garaga calldata golden fixtures + +Artifacts used to verify `generate_circom_groth16_garaga_calldata` +against [Garaga v1.1.0](https://github.com/keep-starknet-strange/garaga/tree/v1.1.0) +`get_groth16_calldata_felt`. + +| File | Role | +|------|------| +| `proof.json` | Test fixture only — builds a `CircomProofResult` for golden tests (not a runtime API input) | +| `public.json` | Test fixture only — public inputs for the fixture `CircomProofResult` | +| `verification_key.json` | Required at runtime (one-time snarkjs zkey export) | +| `expected_garaga_calldata.json` | Generated via `cargo run -p garaga-calldata-tests --bin gen-garaga-calldata-fixture` | + +Regenerate `expected_garaga_calldata.json` after changing parsers or bumping Garaga: + +```bash +cargo run -p garaga-calldata-tests --bin gen-garaga-calldata-fixture +cargo test -p garaga-calldata-tests +``` diff --git a/garaga-calldata-tests/fixtures/bn254/expected_garaga_calldata.json b/garaga-calldata-tests/fixtures/bn254/expected_garaga_calldata.json new file mode 100644 index 000000000..e33e87ec6 --- /dev/null +++ b/garaga-calldata-tests/fixtures/bn254/expected_garaga_calldata.json @@ -0,0 +1,1938 @@ +[ + "1935", + "57844274257777307772353417990", + "7415752482331282167412996571", + "2687083297539612982", + "0", + "38340421798574930729022050280", + "28011636144265328871917824841", + "3220072445478307805", + "0", + "11231486393629225843829034752", + "30531831840031607181867382314", + "2032575872467746527", + "0", + "11055599507684707727184588077", + "28145646756849511230473958148", + "2844586370379752398", + "0", + "67678870967639403492400580531", + "15242471507425651402528895292", + "2223291194660954605", + "0", + "57356907040229837333920171058", + "70484712774762651844279301906", + "757272025908758333", + "0", + "7105217992587080535353305739", + "3363284560023410516641583236", + "107018005293976154", + "0", + "58704034269332553767725526622", + "75767906801646130449699649281", + "2513059269573125838", + "0", + "1", + "185542312681710056866280649521000529616", + "14", + "4791883117158696328437107992", + "17331501240417250045330242170", + "121027932267196210", + "46609243652346460544360498406", + "25080124589553301328883200005", + "190944716053169517", + "32151513863552840621122026190", + "17817640365507635603171071846", + "2312014450301751517", + "58271675869028779769792390183", + "16448401983449010775090569036", + "190765374869500563", + "31538770764718847674853021072", + "43157865692042080606230650644", + "971429148901930327", + "11300568366466207830488330315", + "47117561403685313133264180000", + "2158473445644166709", + "50923409644982390466523481091", + "39762102356049286949241611175", + "438876275539819817", + "66096097129949927801771236422", + "64608035040950255131832227610", + "3106548906736661747", + "69266540806201349013747817067", + "54414680963257284131374655491", + "870196557291371674", + "8084929039237945915662540823", + "5373483804806582444421736706", + "1281135654763372506", + "77239145034620986845931775657", + "24136678221528454376175715270", + "712737032535884782", + "61156998791568778753699088602", + "7660958126211405233147387752", + "2195693293808567922", + "49846489918562737508761197080", + "14475815815553120241488152053", + "3034305777833689718", + "32195478231959029713815134468", + "40404213215860016158630551061", + "2848227421763828837", + "27392476239176695061369374224", + "78044160554652557748476871259", + "521514606300951946", + "3087992549116345894320253134", + "10205992739372366255833476027", + "2847431131874314022", + "51966952838124999501914591104", + "28324014568016433879296672183", + "315353133439962811", + "48719829495829670009861054527", + "58350394945067773716784222552", + "2676736350408271580", + "77107446220213180659388282061", + "7203887993144428971278786529", + "1489657493600652708", + "608372375657372946022403784", + "13400876594013567609427918269", + "2228796304686199053", + "71205322927448619838398870454", + "78962123255076739295985541124", + "571496534217216398", + "1428255389628845479878486815", + "39213893562414348396643987220", + "1749789653399274565", + "27536706371551414439135813718", + "50771406699179464227862505183", + "577924136239936830", + "33736703860213321824180308442", + "77174493920347313850285587234", + "2765906096857432172", + "0", + "0", + "0", + "60184622296806572439997666907", + "75008714795759192705677030670", + "3262785094589981400", + "0", + "0", + "0", + "0", + "0", + "0", + "50185732680358774463548804626", + "10607397758555418006709821705", + "1206124784999809577", + "0", + "0", + "0", + "34", + "23035253095299007202312554060", + "32080256680772227989155277894", + "478427893667872099", + "18336189541437677729385225963", + "37419903970955278964581100267", + "1930748430998166862", + "49608335212638750862702225043", + "10835804751426316920605470613", + "2019800244454836416", + "6246666889430707053626009082", + "12288726737261304419669844422", + "2666138061603480617", + "21405916793901285254656214440", + "3859416321057246363886972559", + "592665603082864360", + "51365405415253778013679904924", + "40102382086317834083953266113", + "841535972650371430", + "17428084733842871231248410057", + "78056943746104429292743741392", + "931342151030285982", + "16042153915376795687516470581", + "42011309273814545048514110311", + "2319465314791424272", + "32117358362766388783857234006", + "64642324223489686522619507725", + "646098400438094575", + "904068250182451375735024814", + "26268058360139979856805714059", + "2323062152413249800", + "62276524685574427494952932732", + "2121739444771058219095273005", + "1151336981320170333", + "90124822835923260097710849", + "22945798417955995875106755702", + "3073707161064064535", + "70288592469382918332080980196", + "13743616935176397546235036534", + "318479199796423188", + "31805202966891380120043785477", + "8430745918641952729484755268", + "2800918882673852163", + "74158272422098022396637305668", + "36542356826981792538318286391", + "583924791638295442", + "77829890526135643352792380281", + "33965880743384940221603167389", + "3358916081460087493", + "63489856339019860771424092681", + "47309349496307880109629399515", + "2010045373371936559", + "71295623555447546022729178696", + "63835381307446101821857585106", + "462349038797594208", + "14525579480417643199590263937", + "7143347428450479114699357860", + "1144142479363286559", + "12483882381207838149531336023", + "40804266202454419825844742413", + "882583989820406928", + "59916233070332421863642057284", + "64887062072552359403814671701", + "507017029246892050", + "31862746468569192262098736067", + "28533030302084706257004865952", + "993931747827158117", + "75064250706458560752176227012", + "63437106587620696752939513942", + "3277189239726741942", + "39167632039910785797941456", + "18140185297742991251319295366", + "666151053619271507", + "10926156771261055424434451551", + "57606677949135316412614193139", + "2561192630440845212", + "70575416102858215759358136994", + "66465978905016970506533573043", + "688835970485158169", + "67397624232833402803262481282", + "41922971787312672080785689247", + "1319822583644266519", + "74251159252927612227699406341", + "35899043748855225188515407068", + "3406887243983006707", + "33194193636154931051739082794", + "65333473786498601470880178479", + "121744865134147784", + "43420103661041508641324900893", + "14441671814648431673279977807", + "1921020283492919611", + "6724088259742225899403503691", + "60143934846068984176923607400", + "2421930040046264686", + "25435975131776000047074228066", + "44192228025335530619404992747", + "3441255698981875708", + "16901194183994789341475302488", + "46844143357014241048243531331", + "3421196951322858201", + "8253405411537145029684907929", + "73241050621420950980363977151", + "2160698513842066318", + "23462125939350662661657090845", + "64361962156192952500525322427", + "403592323357506168", + "533537377843160862760973923", + "26323778860740841887316585928", + "2722669700787004535", + "24791609305676228617259183923", + "53970338324435352100620518208", + "2865771286159063540", + "61039103306426490076835257787", + "40106276989900158886700693933", + "2732318489616688920", + "13879676335393453644107731086", + "78735275839101738515558121989", + "272452974866659019", + "6450129980654748979803720310", + "13527650053921748239262251668", + "2755506203179178622", + "5645117372720054304488913677", + "44920138606863634541948168937", + "128911883793469438", + "52294585040295140916991875403", + "20657245952781433425749873393", + "1346402883258134060", + "4841616777420816154553663082", + "15046309792563663861407650082", + "2924868272635727126", + "7243369416750961178887350080", + "25122585313008895233990797392", + "2542275742026859148", + "63317701440850036695227286818", + "39519959902510763970032070066", + "2979286728407756115", + "70389923165526175008693489981", + "60256008561025470752574057159", + "1790417796404344362", + "41703925602312167682312437822", + "20919437215489770939003698795", + "486901899349468910", + "8568427540015076139572847862", + "2231925582132107264673975830", + "1874125910919069117", + "16733759453712062317348491031", + "25973874834362719585037650011", + "2149492172415741040", + "40432829601940354833775476290", + "22816300488787718347505568944", + "899703849280333699", + "30539743126652633950909991410", + "8246900656235613126045283992", + "2078387053372635926", + "37924762608183601041347271210", + "53836332609286167112130209197", + "983828992066440407", + "22236307667839564082344877305", + "23376389992803132595092816702", + "3185564286118441717", + "56298876569777516747079930832", + "64869672943285564293200695828", + "3025432961561205809", + "31533786315625609412799573683", + "3229290803938611583717303707", + "1492622050000402063", + "22243679111058661988062033963", + "31948302260488949993624638567", + "2562755702353791201", + "10572676750111410687442947999", + "66423122961376176088522567124", + "3152199686317785057", + "41792250128194609168613090080", + "58589039199985059057808593302", + "1249679161730317687", + "61123872384046076133860315532", + "20381369533651411669846737727", + "510605801666236911", + "45369772127144571412068742596", + "76312340823826313643628367667", + "1477863655745836552", + "61712656220585544233153744802", + "77552604428603632451265705285", + "2903778325054968754", + "68590856369861035072011662249", + "3116628645521585089497697364", + "484330904371102297", + "12394100135886203758657912188", + "64530960840754161033953674028", + "1182611748888515185", + "24245406006860086186381712393", + "11056968727511909546563868157", + "2107153872804617678", + "21704933362240364830393024456", + "34889112243577013198676702596", + "1505486511452810208", + "16982689190311969920593354830", + "75275047425915585185130446299", + "2702015084311164069", + "23805798110409022516290301972", + "7302995350001186068470095439", + "2336185079376539874", + "5017625456490870224581818035", + "68430004641242636638033765237", + "472867526430694108", + "68724845343668469703125247931", + "44666974393866543472088179181", + "1822240577164369096", + "62921925758683078053908895960", + "33398934846659882076477851092", + "3043644056833383002", + "29416680701707500617816799836", + "35558718067502043466087859984", + "239874575692390085", + "19204545092869723072698694872", + "34422695291974263067555843838", + "1544692288544869061", + "11617080687003928652500429960", + "75088398415224995795354679848", + "128896729698181137", + "7036024076872468779484848299", + "37769862001090145196410054683", + "1679775632420321237", + "69662440818365227756328106566", + "15330555259423449020458209476", + "383291220274366404", + "15133465329907440631610564191", + "62238402711269901112154324995", + "2177539356900034221", + "78244867332412940530016567837", + "69189862401223124217673234708", + "1027136151923691496", + "25208504669692377705478627462", + "39919768476853720354545315887", + "1721212191066810735", + "66675788856825780766833369398", + "50261027816685487628643035317", + "1465954081779377201", + "841452407261253752605247100", + "37402883861555955734669331879", + "521126555488939808", + "40185544981310697001243814246", + "18484163460775804965414785644", + "1797467046180976537", + "18824278756805727037311992950", + "29635780528243444756818977128", + "726249222316145480", + "68989929465833605455441351828", + "826695546921907884979376652", + "3047236993045624071", + "40692738743445361784535515811", + "15177684834182992014888106509", + "783638643800438573", + "32862688598008468486943950671", + "46955250567175128513635627823", + "449178455875652625", + "52325959875434581183325506955", + "12091737773381120621971369916", + "3033155658420360377", + "59124767985870016725911398567", + "73295690522418841585277319038", + "2603359956137006922", + "61422800228250012257553244419", + "2678866430734830245993427433", + "1286662663232283174", + "52429776566271258181944805725", + "40876378802384308439031539091", + "308229464579228331", + "27519624619534938322694629175", + "42103623075012597748271218141", + "2470400565377648409", + "65641072491539386637001664604", + "23242408951551741454535899111", + "1667431098928673484", + "11821954620091141086569097993", + "6817874298298373402637950786", + "3345818225431439392", + "74442370958577044309302022791", + "50841223583023392643985073606", + "2627839972016092758", + "72650889825920207037451161751", + "66160273027126394446659760391", + "633872820831066925", + "62971186028489624817082481711", + "69343866527061977109414683202", + "1175491839194009670", + "66693206626723446576692797214", + "36471159659629127438136247156", + "347475962022374321", + "74672540307394686827561051357", + "65347746139208740091958133383", + "1460612124007066952", + "28358432542668400321802381956", + "66581299351183150235819307058", + "2338431628963624707", + "37393305159458490325477457675", + "74899760872030167520955157839", + "2747388956890046767", + "21539997307499740843290779786", + "23479495287702280749222879469", + "792430245371898810", + "55477414419651848485581888949", + "57584561075160293426593655206", + "2480366208477468173", + "54482020988750039106641357937", + "10964072031911109104380275634", + "874528608536849589", + "56479333995314163766861392145", + "50262580536350179382757426688", + "973906210850620539", + "72809457096507986730602050050", + "43184270530860386126819634107", + "1316885765762673709", + "56458010765958436589246432647", + "59146615103223257485752719855", + "1007337781659176662", + "15948858103334424578709714654", + "17943382521566065030405843162", + "712997664536602868", + "50194055578186135450192972773", + "71257708620323970578848568335", + "2992307924459501462", + "78442461354068260886225245840", + "46829833134857644929679009240", + "778754522210367922", + "26361234696569719592551466869", + "58810623126016379318636981331", + "2423637109189691361", + "56065276757515095551143794026", + "5578098091848040719186425678", + "2645905832487173362", + "26584842783227761248985978252", + "71494673592402600051228687308", + "731418212137793631", + "12326272171056465275458432689", + "59014106500917591373426037656", + "1363252497310527357", + "23996297979816478309632281847", + "4943972367051664724357176695", + "2977855207418913561", + "47274959816310967408390855257", + "62277561097106156007190443551", + "2378298963781051135", + "25496481489208027992155236229", + "62907962985079879021876968718", + "1429229695311682891", + "3692038908823435294787396120", + "48655508551630061165033250140", + "2166978453190703016", + "35463483465423710501501014236", + "72946193794665847774889617897", + "1462884315430306533", + "76790693841388525896207934989", + "42054747970187265740246061895", + "3085801571148289628", + "52151557012767973461159791164", + "8699843864501847491024418047", + "3141909726296066322", + "48823297189947353333036615149", + "18379865719466121494847917166", + "3365691893927445202", + "37109062995260036719274656712", + "27721839577178154660071701023", + "2688641379661078488", + "38457137664130929508778780848", + "17021705638486552828741391754", + "3456292474207191482", + "66221239715581251837372907545", + "26534933914551929629083618956", + "2695964163435994806", + "7690266362265049133956134481", + "77630093718205233648852168648", + "722173782743846212", + "31315126848238536014673378796", + "61692513765369742324363214619", + "2005730561562339113", + "57153067965050149771960942282", + "17670855761629958660830826410", + "1799099156082926035", + "2031545547137685648644955019", + "60688788866115065168506206490", + "2214913450305832677", + "4325282243206267858104402835", + "45780936409084652853159638519", + "2340742804847282873", + "66151146015906393555465532357", + "73966336244110941687482885225", + "840530216153645495", + "75137729952885712215781633811", + "10666219923390659151083728777", + "3034380245620418241", + "3428346941108654557437902865", + "11333661801915450122349314420", + "949789373691972470", + "69272961212158376957339309131", + "35706948740922611361147315020", + "3413032496551487792", + "25903041086613970510704125517", + "76706279768691818023634502121", + "1074193659980648178", + "64110221451200119788683323297", + "28622292029310065609867650941", + "1884907280971037390", + "15657915604715150517067561110", + "30702937444139958129573215187", + "1277411885881253054", + "35727812059422535955889512539", + "48817756029872636213600712233", + "1743227857965245565", + "7401757965358101100206198391", + "3648203921514477652717474038", + "2640505331822529079", + "11064923401002752620191633773", + "72690819827331058338100140705", + "822690173458042000", + "33604827173192677995894435014", + "39983003217271261285459911165", + "2515456984269384374", + "45650234684410197494316143959", + "2403425363498960927011094399", + "2268420928089257487", + "58110298936972430838324432504", + "35006897688560655905729408642", + "2677015011592311123", + "63991167825523065750493948542", + "38446697222747020672519843067", + "2692918826111445809", + "27672475129757571395259588117", + "39381735598086893956472476638", + "3395853207268908874", + "32854200575808623701715914418", + "42661362857489326128602095350", + "2391200901716932837", + "54150271274914699301480024494", + "6289272448202358045690654302", + "1318663410799701923", + "62549511506267192637586463185", + "64484958886295806459978570972", + "83208658439810678", + "33608942468885090170638991762", + "206657349422825258753614812", + "2393630793315031416", + "68384609704917532917849545895", + "48427081491108655533564580044", + "2089283534419992254", + "26988730150729735124397421171", + "23277608273777722019239499342", + "1562654411531371355", + "47257694163477857505373455620", + "52229085850458173168936010772", + "1555661654885350365", + "31012851371750014525963283940", + "28283034113024512709897737740", + "1736932765964192857", + "27836122708141605661187985539", + "68282944588083136993947327354", + "1509366462238864310", + "27828773722776516828183956380", + "57063146967635285524915490014", + "2149972223761309043", + "26632225286688336592788130857", + "37599962978629647578588181203", + "138161322018481287", + "3824901151039659476484193659", + "13868133946446319157609564439", + "742955232402732814", + "19320916080273430142439970319", + "51819399249108392127730864644", + "2578954938781516420", + "6212924444967043781901762558", + "62650539593334874159192600415", + "1364120547767031951", + "67293595789930257823048139723", + "20619485490393909466575405577", + "2053663889675903149", + "66599032917764476791521796613", + "62237990424471782883073287271", + "205310459710019745", + "58189784922417767004912526415", + "22399847663853849743951461827", + "2547077021517690376", + "28885295822687064305748280353", + "923695163282480711687063448", + "617985169731292446", + "24636438741861390289260690367", + "5507776466746309865418176189", + "1005644282513074380", + "27632954721107371960068074479", + "3927584306228056044159789740", + "700676293170972599", + "9883554038226416766752873828", + "15290717330861587855267181975", + "2270908403486522303", + "45431078529596728120457145740", + "45682097505239100723618960335", + "314848730528192244", + "9381049127998173423938460637", + "72598642631644018178280076350", + "1612232192968286697", + "7506929620671522983934016296", + "54600542840404804898685232111", + "2284445948519072163", + "42916001152565962062558279008", + "43518242492971994959430709407", + "871420558973104530", + "62697587734795456584609903058", + "50727406914624514448924367244", + "426160454752781099", + "20147749471461920172053151720", + "28027097409898003659719947266", + "169482123170283369", + "78392332567170737493535544744", + "29499445717776177826501640112", + "1385306376630516984", + "37359912295826034348152747844", + "44203221020989032071809589760", + "3379525949362022594", + "27775353562463235233845980649", + "60093710148642296052460963865", + "376899654559617683", + "24802163206900264998049467888", + "18079780512465877302680780852", + "2436405115197484199", + "53402800301833750274442805282", + "72465483623284771287314335267", + "1665152351189318901", + "8802990148956570495140707735", + "76940129806881555823918051587", + "2279533134645947500", + "39139361160139491758849894836", + "47403798770723346131562329738", + "1871789601957934582", + "40155006943952538849210354555", + "10158497178229493924826758046", + "384459254760857874", + "31348408056904175530058262206", + "58634179529918021468775614390", + "2640399076897540766", + "38334572403039032475660708552", + "70189045061204182075484208142", + "591806042250147986", + "10330395068436234754481602473", + "50338220653043272338573553208", + "88711095816256366", + "58544479684603572793656495533", + "48863642128580723242189381333", + "3292771695811146989", + "43382529075192314114273317197", + "52701361950672365507115476497", + "2675021271158818553", + "59989944514384115989887626117", + "43683036232032261202372237193", + "500265640615175463", + "12679793182528011992068061794", + "78011470405899630193572806718", + "1558281431877142665", + "38105876290372694006018545164", + "43838492068014640506228270754", + "2351302174983257893", + "21315654685015546513724846151", + "77969092174107923849539244529", + "886092623875638058", + "25185349771645775757816238535", + "60102102664262440347011347843", + "241272462356528969", + "55606711006539872166021881967", + "67026947679610775980908771780", + "2926111633187660134", + "62253886332495849806845214596", + "22195336131958729944885665027", + "3104512835357395242", + "27777492081255714444632912142", + "64370054324635213535948910796", + "3416702531238208301", + "56227335849522527607586013875", + "43325119340157654042648980626", + "2634434982001224414", + "78514402871162165434495186092", + "43426198153402611755612768897", + "2593196649840751518", + "66698722396386436323417454398", + "3837553656690720121126150016", + "942883724980557371", + "65752758928006535698277835168", + "38318579306873960611434576922", + "3250368900185476355", + "50495783590960690870540691790", + "14653325799023335920209444740", + "2546625584039236244", + "16630028107387223808965761239", + "13863181193379294654760296622", + "34464227120635586", + "36222872711091596428786911842", + "51937668549746425466537167608", + "794130220777240294", + "62504354186529036229468303798", + "69736977601780992218404196903", + "3349190847428855696", + "77469677140987986628555279814", + "66181254387246930391846178828", + "1094982751282319827", + "42704982966835880096530026566", + "61183850071912676297661083421", + "1443176298222155013", + "458000883646363693059951738", + "68329701428977096722489784095", + "975571025619009759", + "33654927209224611164703917093", + "24068800611386661573336373809", + "3375201202083086431", + "38833935598284136694087261021", + "59077868958235065587892735849", + "1454556414164578716", + "26270682702656259827679435279", + "65539860928914611448387770350", + "801298358572249630", + "15673861913919620903745120210", + "14692334517011320679354136946", + "2821097383277721091", + "39242137586747887757437333332", + "9083122686875183606330701458", + "1921373787864102811", + "41144926811977123507177847147", + "34472011718104956762776193205", + "1146349616779561564", + "574412587454295809008190233", + "22875791731818926869458658642", + "290948127163017881", + "37087318612539054198594746648", + "32681976987277353078355490178", + "2406184781127438137", + "6933243496812646276118612288", + "54651790577216254823853510289", + "2701858329857037850", + "56139774594909743388355739001", + "77089327312458418112180476537", + "3266822879537254951", + "54834639174453678089594792239", + "69668657071142491833418215283", + "326495760786151287", + "20426164019873972172998849041", + "3252166954714146103884599328", + "3414541191436319808", + "2752942956009571506878282330", + "57396441209772620890857904908", + "3208295307637984231", + "13152740460737626286764098341", + "33025216675423004606786579921", + "2845983967622870717", + "64734827687104406253148718857", + "11863596233289391273349852965", + "834842894363203798", + "51666517464944131014506151397", + "59314297506855540619185504628", + "439539499814455616", + "64380785983189647725990110644", + "38570979316883825078680465683", + "1150352146339595098", + "25067532426164130034580108311", + "37446320044920551801876012557", + "2620754637534843304", + "42808069022734665648646280482", + "19407294779037794642197529127", + "2321923266102810936", + "13834333154587437681654406926", + "76573280845370549677024963648", + "1570750191644163609", + "68931318481216014090676731789", + "53429203295108999630447194522", + "1554287460062328195", + "54987423372748493678467051473", + "40767075806332185694854429433", + "1169000075483999060", + "74250522578609099473334809572", + "3332557926593819633541279173", + "405639687648804118", + "48248941073200222469938704227", + "43787244471213359091908442844", + "2477224001416568264", + "23776843130656833107440629473", + "3423011339685348877237093898", + "3005010070248881599", + "27648165163010907281909327015", + "61450018261701903371866285153", + "1327094418769208886", + "30961349892231714416349729377", + "75966864764765729032315134465", + "1133023783192131207", + "18684767419719501368592247832", + "35886886499740903171668498048", + "1420090124836343498", + "43758358660126954972909723443", + "65499537160775804138474114775", + "1215773052038185400", + "4893574830978831475703941323", + "13944518284948023471817009922", + "3087770676187315685", + "63026731479111866531311215963", + "74994082204780050475722141820", + "868059924700373827", + "28424789449172317184898776601", + "75580753692795253447074806493", + "2925170237974201540", + "5539466445829400355649376677", + "14300041494696670946528458237", + "3353400155607299496", + "37645445495262989319326322445", + "52894200901839147928700782027", + "2405559767924632715", + "25554948567140497222957189064", + "13742263843484449168499336324", + "1671115139660594966", + "61446406976247670620569860939", + "35615654529034960637103328730", + "399229004607548670", + "56163505916193018973686298254", + "43976163990461076344578051442", + "2729581018549170384", + "22066454112828978516482512242", + "31719173706337827302415416949", + "398690560390424852", + "35374890969681823880014073896", + "36843428673923102166667110584", + "2469969732902925931", + "54560625297668853440319861171", + "62777526031538027798796569756", + "2993516567667036501", + "37922860807812364190249087210", + "29896589788033859935663224668", + "309779372168384560", + "24455247885577518488087458645", + "68823288608393449144830127703", + "814882265094697556", + "1130967007229972979607782583", + "61830444184272400549717067717", + "257559017496993334", + "58133476540138276439645440051", + "25702496251232856385544877927", + "238479181773517745", + "26999152050803265193193188931", + "59001428633107781874894942650", + "1584907031546890153", + "11082858404571259635212025131", + "57555984117702121991871412262", + "2878553798870122842", + "75367866839475585566939377943", + "33431451909242664679739698707", + "3191072546898201040", + "75505238672663201943737348522", + "56868097693796809686795764587", + "3277333858882651020", + "43187088729629060155700009323", + "196964351178094145972885906", + "154518068128561288", + "61637000900486583609180618390", + "12563823951101453448294706734", + "1635392222588550285", + "74402731945026060775403233111", + "41125965379401953572532815254", + "1810062541931562681", + "33646198859852776152493626558", + "44706708611052237167421258040", + "37484451833168315", + "56607861506406656533289744288", + "33277490632081170357640403024", + "411080497351910575", + "54161748196046656415586696616", + "57843736619157972484861376729", + "1309813965049914801", + "53707016211689656476659791290", + "67397885248876373162230107589", + "810784356534347845", + "55813013956070843639966549502", + "65457352085858621067703807190", + "1180705495920435081", + "4021299859749918817435963968", + "25324681437655807431262307148", + "2857964377950554591", + "38944761929153439743888787898", + "63327899064129885425751585478", + "3380248592968146775", + "4106020784765395626137239126", + "36117738103147158099522308877", + "928728116677331888", + "39589303831779102119145491754", + "68860328057344308157770641537", + "2891816410909653138", + "61329361586502192571007818625", + "24672674575412726529369490481", + "3105683157710494537", + "33857779361258958946202968661", + "42323628202573727967587848658", + "1293483760294808152", + "38642587259244665553285396528", + "14731554994151110387076571784", + "1516500958979226542", + "10385030987488039299032375717", + "12467887864445536286013101693", + "1400091481142240539", + "29792808745005602732280886801", + "53107752661066949050032104856", + "604398020189154789", + "8335987774524913636526501050", + "47091995985618270387724885740", + "370799868965226603", + "18407252121147829261761659170", + "78444390451072261565148748703", + "124240714262833840", + "14910956979312004513806852173", + "37456316079517019089385886562", + "1318005750877936723", + "19013620435955281117273595915", + "18171681417384550803386117614", + "1441373839919056712", + "68212171432118828931498635482", + "6775202570091060696223110895", + "494408949444294670", + "48962575810326593997115590347", + "67064311579703081676346173307", + "206058401823194139", + "25398481582148968520246132464", + "50776804771264131736474555575", + "1638168281446045440", + "21810728528661780647093483718", + "51125544110818737659097599553", + "1676237618560187381", + "44810175989539740659059827972", + "32856728678519542806762187931", + "3240660902289240878", + "62656227855265203007932027687", + "53260317552718179138189580918", + "212930269464699861", + "63690204554633252943131021299", + "15246761650174894536707121920", + "2202841277097838816", + "25412880736259677152733039221", + "65335855903579588094097298440", + "2945609727521132479", + "48331614205247858281891142376", + "66025048239329838282732019230", + "557929556332431689", + "65118155156224362777315158460", + "55848532819672355228291028350", + "821661997507432690", + "41778675729155154156962220382", + "19759251639554103548024203404", + "29141939513618288", + "27270332571857639442762803517", + "44271276623209746365370291090", + "2665239998555074360", + "44162757797421783229883506140", + "40693616836577930727962511547", + "2980951274220808357", + "72480262804409524760366412347", + "74325917478142923304246649795", + "2130582734163054586", + "32903867013683915845998567019", + "20350795145701791581251445969", + "644794566022213951", + "61344758852736232937372999832", + "69605971638524624848709856327", + "1294180884444811474", + "60166071748209490529186046713", + "29937198622545329319528051088", + "2017551521732442569", + "22035272842755126087156003595", + "53938296990073102738797041990", + "692624842323882809", + "6331242127103731010611103862", + "38617004467243561009303009231", + "3464688190425208900", + "23350722503406381404160802905", + "61689683103062563874202872331", + "2241585172305927165", + "30405041425209404049886896756", + "35752279614566252436479605977", + "3410971212589977316", + "68442530076706089420844078272", + "17721629398851067497572965483", + "1728533538572177984", + "34841146984959956954989553961", + "42432245701387592314305333111", + "1356950247820885617", + "43017611831188106502351778325", + "56701920721136574174352312512", + "3306041338637770805", + "1018829333374872207843306468", + "56373576087292242071519764743", + "1593946427382357589", + "47006431101835194179832164729", + "64598165246888886583898554241", + "431277355598591352", + "16010537016178217853601904713", + "4785440240747782184616696585", + "546196005701584202", + "77828072837711712399140741534", + "23423831785077285604916105426", + "3070369678898318470", + "16961581663343714608407074233", + "59009791302688352202401204640", + "2119768355013678932", + "20463585155729216801225436663", + "25471371453329102588261106033", + "1029890333203018413", + "32672325572992882683414728677", + "57471395191447538892367258124", + "1330888187409535966", + "38299197656806438412185288244", + "19271781948666485924033391186", + "227256351819715025", + "40081685665380239960980230034", + "77462066307125453989947618052", + "1881678833702501568", + "49848381345866402020045431200", + "31892121208666367145366170376", + "74714815056270405", + "52512147839282193500014892886", + "25549033056060534772997338129", + "1596335881874507272", + "49813741627977778279233947352", + "4008095573055068993371546891", + "3195042096943182404", + "26165478919815264260510513493", + "46247710558154426878169750434", + "1214781396283379952", + "33121613410818326512248478008", + "29687910928563432287246935517", + "1802142974213369467", + "59523700707112127217729224913", + "61651878191277423949898345438", + "2035609720350983544", + "51972910375501412458946973687", + "56195289017785478243773732259", + "435232978064628799", + "12079761702596075495921541409", + "35127943180527776492442527195", + "1143284367176688109", + "20306589543653615415066600693", + "31639811930753004870493474837", + "1224770005925561436", + "71687204625456604081337951083", + "27507044735695201444550260460", + "3307601860067092586", + "69380644851449148014790668095", + "69993113541801215556191633702", + "2106384362510611565", + "36366221928196258873498344464", + "56547988185992504118210277148", + "3380313710779095295", + "31040533335624124639959881605", + "37784035908434743527568293248", + "3382154391521870612", + "44947556304676703348119024244", + "70183427940693053567523352727", + "1650927292986121953", + "61381946239453121950845817346", + "18293751119477600934355796397", + "2147292747573340874", + "66521173025941132529836001513", + "24734198503870919969457561484", + "1006951780586497348", + "12921673142729423584814452765", + "63302501548050937864284215269", + "2395923861627505982", + "15985379690914051998728549265", + "64573432053725693188054482164", + "1847610610978458880", + "51567832177796936547699712853", + "68065425985141490376121850502", + "1982293592175031141", + "57652434354020213690672235811", + "19537723021566755411457438801", + "3136792556383008191", + "16219053988218181740471550340", + "22103258275792994305585862644", + "3364127332099229410", + "60320003495904578982034612276", + "4998360579965635171563474843", + "2371286711922437626", + "18030944953869826314457223774", + "13527693104026157000416475897", + "701301391731496607", + "65433237994201735739877668578", + "35639579987806099846958346999", + "3138977811325377810", + "72433019688196766324245831213", + "44012136576320680271598336636", + "260767717114497208", + "46887343189243671181789531887", + "21921025587452582102025604328", + "2128677607431882153", + "29350971386462929114666111463", + "45728975226748583439149415055", + "3270578587979411611", + "5094415249190483182604534506", + "76808850926739826615091966194", + "203642098174359221", + "53775437415528159438591755317", + "14238024853806697628347373385", + "2057999438891020928", + "58028428102718567620982499300", + "68997794895471029761191295031", + "2746315904374690306", + "1717114357581958560313166857", + "5213627699927513856084118769", + "913456412487228993", + "32316843107390089555276217733", + "71007405521576107362776659519", + "2122540689746777227", + "48148556153832233018577272199", + "38471677646254142570488025430", + "348053130495937523", + "50400909486637374890704231694", + "54778976012807349826116679323", + "2944052227768517832", + "59139796312492657056692949411", + "2061532885863517236257244671", + "10243765605500365", + "25884543163281662098973524847", + "37916895278426683903234823755", + "1865126889593445594", + "66197208571270325134838998152", + "68545376024001833893210521274", + "1188089499212513230", + "75441699303859750263301381742", + "67645766276359806894041033577", + "2663215845879332085", + "58650491257905924068608792715", + "60115611283504781052614169914", + "744627122690459780", + "18997642386388434121560143060", + "72790714878162005698916806493", + "623530264443505303", + "31720002413820256421547236095", + "46416508163013223188304045919", + "1658041828782166040", + "24824472134837939407422254618", + "48291291681977470757114037284", + "424087504692641762", + "22863956215986707623588419755", + "46743175292926982322966549922", + "1609163833548123479", + "9869425883441335618145770058", + "7407520076294537606283404141", + "3309926797035351444", + "17571176382822194552667894545", + "75071155084832513493942967758", + "2907959396491327183", + "59948985645030180546029973825", + "65410892940573694939321813134", + "249228651794920073", + "7152696297012952538005131999", + "74254517079051162005835622204", + "1321085918305058056", + "21747577669965730751204013033", + "62371959795392031822025273512", + "2860235133885549897", + "50158116657857687016226755421", + "38600067962112065115416495363", + "681833181674316948", + "50641253153581581909077030811", + "43501037763224203033596042064", + "1675139521121226545", + "29879129918407287772926288686", + "45866277938795658132883957642", + "3223033119701694488", + "26791948760111543235403211354", + "20874895950657351273404969247", + "2993599759413014560", + "25118109267963689087907374108", + "45986826845870844433059705779", + "1774709006621518026", + "35853042946704344435352445068", + "55966536296613174034068062987", + "1869918869843978405", + "67759695446692760457553957323", + "11285860729751980300856513092", + "1545483055989275063", + "62737363739381604261966587492", + "79071052627385683701583273096", + "2938509175978254335", + "52536153512001066197787771905", + "56643733462200484956208400952", + "3404789854849323840", + "535701273287851951425736591", + "123689195120925855701879485", + "3307485001464244869", + "77129857239425473829140768692", + "18091892727767083201239111162", + "1291885801161055718", + "53060264994242623985016455823", + "51051302551837566483889783363", + "2955893538461044009", + "36588320368538893217667915795", + "41537811631876375150744946884", + "1389016510133160646", + "64232826272711972901247847057", + "2562614493130150333240390512", + "2279066087836205599", + "52916125449405150339077098378", + "65835152883192147775358731199", + "3007657578285281021", + "71476335294222387145395463221", + "11787939398734514720056338070", + "937745593452538312", + "71101549691614935452066801647", + "36722747907089637926994528819", + "2277004148579735647", + "342139859208823398284772838", + "60957071198465472943968461534", + "1816261238822375458", + "47674950750450131344821384964", + "30310254140102524882740784239", + "1241627052133072917", + "43468914777996872906900639261", + "47132252672283235272329047387", + "3192940200169149337", + "15872631049582825586364952393", + "9709184487638345712089630890", + "2838397153657804161", + "29390176504476737539701603893", + "20843419224969966952065335519", + "39871785745660896", + "34228066246071074541239636763", + "30927341150981646948832399546", + "1706743879711887611", + "56167588406649801717516704493", + "44570619251078156190812506724", + "183365872080022443", + "64674673734812368247721551724", + "12378939856411739632972234035", + "3114339607349343773", + "12158125384011836409909410177", + "14615794912168469247107844687", + "556884776837144363", + "1336429616077789874888326943", + "24213610066290273904652524696", + "1083155009341854883", + "12773611339249793943018851630", + "42848900220193466998411349044", + "652769844609104675", + "75898462890787577892684204846", + "25741535761264076344475377291", + "2100494261797072585", + "49481208247611279996106143384", + "3398223378159398014871555553", + "714504252238150473", + "29545685242368913332619033854", + "5625336249132848511217436955", + "476411276815261273", + "55890660458920841676138669819", + "34941663664064486964949638502", + "517974927637620355", + "4028679333724519343502603505", + "61566535213758291524569377439", + "3456825035662652285", + "55571499211009045514988686572", + "21790443436967194792420043350", + "1969342396555785632", + "75206790879948059455586832495", + "16717179522990850086856772064", + "2704778620335805990", + "63454463664973385807680707070", + "28691308337854187221768619141", + "213040616647656383", + "5059812635829860167788494422", + "15243413733103127632683633902", + "3020871464553522020", + "33399479422464228524370711311", + "71920370432711593116305850378", + "70051540797500860", + "38720809181021849432281915537", + "71926907877028179546558682722", + "1294049622219492228", + "38555961895256839476706836290", + "78965875881535712525848770921", + "2800180418902316014", + "7572163586620248505682262454", + "12826017934041386886426441824", + "250565020870865769", + "36013796440617653790779192957", + "69166108013462104697702737800", + "2611456563598985633", + "5688028504967502494398020661", + "43659826937874181855848320345", + "2854671851947864373", + "27868929427872438436197568640", + "63323499021200741053170406782", + "2273093139713161627", + "14558460832146686713723510814", + "43476931346375484677881316187", + "3383583256042294444", + "31560057128698864062140643039", + "68133077195535820744132661519", + "200620479054014854", + "63995354067329049425478345983", + "25191242150805596999775595611", + "2079071326570743360", + "66950726515806303950626524095", + "60318396580289126399075513798", + "2454647708149088357", + "61935620353997812117799662566", + "71353577562076595604093535607", + "3412191369006827316", + "543819455896725427113354081", + "34272198929120959314861515668", + "2827595479758818611", + "29410993635995602210089737779", + "14356816112136760233570978254", + "2499183482782327986", + "56632814849798326824193274444", + "45342834652719580542464472178", + "2204249993449736418", + "26521346246062458165692021083", + "302495189721568144135453800", + "2127668099109629822", + "46124446616446295256668362905", + "63663592746898132263269494034", + "3437009132207662290", + "33102774162255893173757746900", + "68716931690027649678145681940", + "171990903146040065", + "19054338954968864503690144516", + "25284024094777868941122053978", + "186015868943382590", + "190", + "43251614323161113984086827846", + "66218437065253314405126204916", + "2317094031714433939", + "11953766006567965022913115618", + "9623345323117884856861906582", + "2357366244642434233", + "50013610976212970114427716782", + "60486231591615565069325315125", + "1338715101528857620", + "7729631368146545808232690228", + "70080862200369068155833529197", + "424163780703773738", + "66289999475445595255187316246", + "16320632983760731620776708003", + "1703731549011620813", + "9749609316662341636934466202", + "41176611670707446656699332758", + "3254722975687383765", + "77862301916867743250456797453", + "72029692666199591860362024933", + "676733061670018836", + "1726583975868454738987575436", + "22682576024616158189012802588", + "290521460626166744", + "35108490392501656660500929712", + "66608899768977876315758670259", + "2678117942707023530", + "76469349139580150048713605246", + "67152055109401804998456930101", + "1629332114024605954", + "11277139516630836029329861158", + "37489834489324379542666158515", + "1974594890115147051", + "9649895275512686855126109863", + "12365028137262076279527737818", + "1341333051480178777", + "50572240810327204147057612142", + "7753594745014320608005954050", + "242773123303459154", + "10629564876984957624702015474", + "38129077398797720340260521007", + "2662320149106605018", + "38058547219543322966823489844", + "13158549279957212822687883766", + "1435968301618060344", + "32035055088028281449746024716", + "61899092380178004381023573225", + "1909024702880893546", + "51036294182796703443645800764", + "54517849585420249353140194645", + "379526759956156358", + "75362855185144121046134061743", + "78336687772618397926376380908", + "2560893735818744330", + "27399883906273584505552438211", + "33251951593563464257389218805", + "2312981313110477570", + "72156449811280839214159743000", + "29500235918623308851415109357", + "520578525019932845", + "13198450968605550879111794795", + "1073514789173304786963186186", + "2864964160615184822", + "46117628303384298983589534652", + "38914261508848310689443576243", + "2847842945040494295", + "17513893224228969012970643152", + "49903364419289760005151487107", + "336578357355111513", + "44813584833046674275100964867", + "36101217576198623493898338972", + "531348817061619888", + "23355595320925158470632634529", + "4976532712282730176605700616", + "2097170047338095081", + "35240408484949895541259375626", + "28556863198511611270140949064", + "2844032456995286669", + "38854427682435475288524532200", + "2991008556719500366779567753", + "1482996523767958953", + "2781692080205097611078854985", + "4858422932202938341750957102", + "456000300077953728", + "48622056166470957739942434514", + "27016985260484450459742283383", + "1156554873587569840", + "44254099368661466983747048199", + "53396569572501872353853532193", + "3212271986227353853", + "11663068183563490648490142508", + "48052260094923705762009802662", + "894058120868070391", + "52083775820431436910855046686", + "68042464125188969721205795683", + "2667561089742819026", + "36817024564721555650804793124", + "45744574494817926713764877158", + "464913129359538890", + "12629483117484242794478013671", + "25725861760871936465719814840", + "2311568849835145616", + "58574555621506260512634879766", + "70841137732938389119142854407", + "607824277207878623", + "2532725977079368169896447982", + "79204015620401963996092200308", + "2948718411805010060", + "75615695422663002966190726716", + "26975216906603145657932756851", + "43403261860296499", + "50321545557149082586376487350", + "12571419111143381339069263730", + "1468582486504480948", + "41608691081688829246199657244", + "67688177912611369544485161426", + "1577674944591118874", + "69851707818130740742401030061", + "69818325513458214579066980280", + "3056835400261766115", + "14433002462761507619173518786", + "46537124569874012250868988725", + "1206986184975127741", + "27553461663654068917995668953", + "7600760896491012845445678670", + "89813259753737820", + "42750372639814979780510559047", + "72358426234069238491702387036", + "287990644316245621", + "56673418102025027531499473103", + "9426025185793644841525893492", + "1894838761296393989", + "18756855158042435136547944152", + "44316354415833306573841143168", + "3290838165673307910", + "4839113317353226145993894686", + "67749278820709397145973540579", + "3276436897862912819", + "46214960467256099634506814178", + "28105686044073975544826665748", + "30489942960692858", + "28631199169784350545143752712", + "29638819733455437584532200375", + "1717544787012699693", + "60387059049601019776937487272", + "52860487093716738125180737272", + "2003647110924891968", + "72083315852143050599863661628", + "13658076893962142704609829117", + "2377898034726111681", + "672297533142882962594212722", + "5335764909384720979003209035", + "2075060485603783076", + "8651285741697090701732139603", + "41844130219077314368888032721", + "1372534415630457429", + "12824503896344786500849485592", + "41115845124912167317379150643", + "2749931878504937594", + "59048833076938445783152488098", + "18245939560152776433320272114", + "1542097521308132791", + "72922923610265112911518346761", + "18800683385254710665422391374", + "371871334951768509", + "62597954804837733476708546403", + "2299491030759412560600627494", + "410037472279889223", + "11495043413558421663800606857", + "75082267390740344669336426279", + "38377628251471439", + "79195908694520591699161446727", + "67493118381466254761230473546", + "939554155751220214", + "52398634342960574523901991091", + "45802531738678274091677248671", + "3376602817516781404", + "56405319832605586375004145591", + "67248163920250454681310374813", + "3020414869525692015", + "34734931632617227121872549101", + "3739736620813073478862299863", + "2749864871528755916", + "23074613221433267127960758942", + "54949046787366730119237548767", + "2168577218840670689", + "32675874752508678831331428236", + "56575482032576481205808215851", + "2881206673722192768", + "37461501104168767768011376900", + "44991194362570481834887348265", + "3131345308244033886", + "62355998666570257580398763489", + "47504282986300017813562221017", + "662052300566965722", + "59170445006709825448061179532", + "66126254786479651674223160365", + "2987604025429680581", + "27803099085929465323030112728", + "31696288009150296297398247213", + "2203059232136905272", + "65234260360834586104807761902", + "20378768133384010295454501457", + "3023118100505939931", + "10875339989011280041312217492", + "36765492967342656900584726688", + "1981604885716764136", + "34191615334402682426714542088", + "65785390920463700073684715422", + "259117591096211795", + "13182459099890677393092806292", + "36364036179615134779186284888", + "2040990830057776250", + "10562501491133970308539436034", + "75403021542655288921975351225", + "1491944241551902779", + "12853848270150790976694043507", + "39969033429163426347121888587", + "1090808233033520092", + "54409095710681624661134564226", + "24926829101714534351512778985", + "1934495152560868172", + "1635272234961097681407542091", + "75197575564946718862132658853", + "666049392458142511", + "70108412439720064531860208082", + "47132489130477062926954959561", + "3456651348410636342", + "32342687530753965126397576145", + "50019533799278308402508493105", + "958138058056135831", + "62170710639582739852371711363", + "24290955839380025831121300681", + "2003909190176259578", + "7191421406541226577377106148", + "44431405026151929838191761059", + "889887994738552400", + "74515676054614874673052585073", + "49228485666105666308903780887", + "1105016819846418089", + "64346247021674980139737314248", + "24153554603017198651611988051", + "2456038520957065413", + "62961408798099066510359358310", + "51521470756729762854219764861", + "30551904379812984", + "69807301779474453090528686288", + "69613238970188202663624961278", + "2644406654161468741", + "11314534390418842541290460209", + "17642060596009506113112945561", + "3217083745030676008", + "64101513270144822884923200482", + "28764095118292805367041180651", + "406036640563628824", + "27659165967551809502673405856", + "77754936683128423849932875885", + "2023565169487844226", + "41920746354242045571995393379", + "25430473373587923169653050195", + "335583069595939645", + "28473799096149959447823942468", + "31514472289261827292733036963", + "3375007035378704629", + "32357833472063262114673388932", + "43114155184147960029950335471", + "914629850278942402", + "73687521701600056572388937076", + "58961927795766037185303872000", + "184352404333943113", + "34245508515249268224000114545", + "78752827674629416186474400264", + "4469165693387991", + "74649068342699136590805535171", + "39008006667016582663553535790", + "1465706947721988981", + "13227041091770320687170239455", + "53854412510881319420424824067", + "2736320723748063216", + "40865470083945880043410404268", + "17107457733838951085347526124", + "1878547939229352545", + "65293931808254028956215779009", + "24971941894405602062620180615", + "2063502258682081191", + "75502750428793172722913685413", + "2178493567386140615476152279", + "1696656845886081120", + "55246349991862875470941083558", + "48606328740576294628886792640", + "907943242806976130", + "53156049400979654901086438710", + "48543587360511713585589192089", + "3203433767166711718", + "65967859512841255410131926053", + "29597185486273534345342381617", + "1189321819527601318", + "30008954958473241642250786470", + "32087519662752822949712885609", + "104715074828020879", + "11185751191824667896991138994", + "74763842990857980906680721076", + "2835002843672233576", + "78593257836876753003428454248", + "3673486875261635749404488437", + "49119749258664035", + "34532232698875553841927079613", + "26292513168023845603421981884", + "3072627762368535504", + "42507403741825412199914030681", + "76900348223936795414340158538", + "519830489362145106", + "38017487839776346351565271670", + "32438653696901146252680049942", + "1611598938346271294", + "18095810473356207682448103162", + "19451374814789750395102453171", + "2284042977843695457", + "1787224414056378961538768588", + "29994724353377075971017409982", + "1563151776544529599", + "72458589095264712350717782826", + "52662650381393894655782556558", + "379551860916490747", + "26631600723556243364568908740", + "56275825996042800895335451565", + "2139290246957890857", + "48969241709708514409724715931", + "44849517535255170700410280934", + "2046947261531718340", + "35661741261220254925811525956", + "20162709368624376102868845253", + "824147179930154239", + "74096635948836513152306996249", + "71036229528410315390354350006", + "84620072806224780", + "62141508408451046546983115374", + "31965899890302647280692800013", + "1016299733919671763", + "5557033911912806405270016881", + "50435591509057643957334274066", + "760523074590619293", + "76114039807148595960998163616", + "34147707741338084358394160835", + "2424501198141005168", + "73801725962561809266860021769", + "18699961305407492715871817776", + "1225303690713927060", + "46224281622333849688040655734", + "11639195332585766089209684359", + "1796083302683092632", + "350949476261571201915968855", + "73582698223594216566939684622", + "2522866647114770811", + "64860686636757256608293244413", + "49437965251883141668693526102", + "1808662476284845936", + "24133149553676052337775883183", + "68249295354026133761393110904", + "2304042200854244266", + "20032808988899029976888212297", + "72368831791129146511813611464", + "1300943672428698069", + "37131454915089982565256083386", + "28708110170652046088984456577", + "1124653614631242358", + "77525154848079957115949222322", + "61592437433378865527998540660", + "2973189109101511929", + "77339816198656483348500413105", + "13960745375090864540790536202", + "928690321665243161", + "52321483018583741221580268925", + "20617935171522725982902902922", + "439017516057259197", + "49251351993773855409408904707", + "54245120274886777617143239219", + "32824245746775877", + "16058101701505696841021516191", + "22695543864690765266835281763", + "238104254672848583", + "54628788382382263273391098927", + "50765494026575793065621188355", + "218738781729681461", + "68825269198956253617140075239", + "5362741327514430578832588870", + "1753410550636792445", + "44055949992209886691909968155", + "26856668252089618810227495038", + "36063325000252745", + "66575645872720698904701114193", + "49654763559388946168077829523", + "1856394501870689013", + "32558465390496860176794565644", + "13829367702934400587109907", + "1022787216522148700", + "5921356805873151438080214885", + "76861964832267760099064533855", + "1158402312666181939", + "53671056452945681502540601314", + "72268712259173121140826444196", + "2110862816031255505", + "17522441044387563164174145057", + "67104233513001270832838710320", + "2491648149650535291", + "55759050816841980676225110693", + "1840775385523481815247721898", + "1544859900753228381", + "40508325331422732980880333366", + "5670816540383755495583000094", + "262717684209059488", + "59703405813863218796860847444", + "62889967392635647178153348857", + "639961381212439065", + "63523630965156923674378327012", + "61676153301474324496231591462", + "3222607551533522248", + "72468874903813112287307202113", + "2062409111719670565344542998", + "640026077796102198", + "46401221822531603505656635917", + "56017513070355114016698228704", + "1711366645511998764", + "19898713459008786834928072313", + "68650940003050197510843335441", + "2974816021601620406", + "50345673118266674498888801632", + "49869801037603528637147966345", + "524660987474057021", + "74912873871614489872934228149", + "63119535523716705143637524189", + "1970724808215666334", + "29520824641439557338397164956", + "60707126037747743338905558750", + "517853016951083652", + "26077251999175397844282836710", + "70361589640004652416071798426", + "909439460128540312", + "43510936490768312383134819412", + "47358622845257182586484666349", + "2821761255035490613", + "66225144722979143511106625026", + "19823844558889029247341559676", + "2475026994351629183", + "14755447950025129135438270034", + "40056113191019262011521778026", + "793072874256329658", + "73681223465737470939729588260", + "20223090508948548693544218468", + "792001554445167961", + "29197573629931517940875239616", + "72888243327985428835304215630", + "2911430469154897672", + "34462003157538032873601322530", + "54677431353273044655139295125", + "2191590948981981296", + "66793226275095562197661556401", + "35705706246608652182020347093", + "798836539302837865", + "33925482305813114897550265080", + "50686182779988153139631859826", + "2258391340755499633", + "64237828410492793425587342467", + "26069049782347499909541331747", + "1373204870659758826", + "67422579037005527376503392357", + "38010795334039608475441172494", + "2922314236989993225", + "34087316459167286270377208214", + "65429285490995638906597324670", + "1459720251741523178", + "18431653665782456714472977651", + "49428067609744098061899013850", + "2781163745497758446", + "21577134206112676906624825506", + "61280865946143081924951547362", + "2859071040345065200", + "38184724548064163814209476830", + "36814082667749604693868967719", + "1552699264121961596", + "29625449920983939561295176765", + "16313312527296221110054461290", + "3196033204524973674", + "44868721710625986478328174415", + "52658245519401839553383802637", + "2428060003409390340", + "23495060391577362549009273476", + "69163992394654167975887793637", + "3205300885531147201", + "19657207999232485296582569646", + "28406646775407885303792363136", + "24581433686666900", + "61632450211773622769650235807", + "20086409763092603979543512516", + "3187676625311902294", + "44317459486560783723019224677", + "10492066560358547506876637913", + "2663269944452763001", + "49928025721994878626504600575", + "16633378312301016100261688689", + "1059535155162832874", + "78118139287090877628700741034", + "51801115532762241823571977041", + "2866477599734699437", + "47456264599504718689254824880", + "18019769009971376993929419626", + "489453009226118341", + "16110753729092821592193047484", + "38801718540726002984851802143", + "142020636090582816", + "21542623770027438289325741289", + "34330981996603261389125043386", + "468508008327558134", + "9741081402845325198678626028", + "53072775827222250151985625308", + "2716995992584398955", + "6957113485331455801556398879", + "23820461461116791331493976602", + "3048228056524052626", + "39448182236633317006430643688", + "64584135483008140877000483432", + "1369585661846012787", + "57438995262665036407858652944", + "73037143549666506709517951665", + "2809049264030222375", + "13567257428912406584933031609", + "75491047627328950086360051073", + "1442659435701468070", + "78680851165321736332661797782", + "25013008220807270360844441945", + "191557266027139737", + "17329691274505223395266514665", + "44390456843325529740553788740", + "1654998318442768910", + "57526425353729673942568345922", + "50502205508873735978550883006", + "1229447265791140790", + "2946944169528739617063855588", + "53362861125324855276722488981", + "2259001207961260296", + "15933550869626801756670972143", + "72533008323843814001151900125", + "1893362946815006557", + "46387294791180932528323513146", + "55441564660350017372593215269", + "1543762965962291395", + "36621813402081195689180722055", + "25972233302916686818681750759", + "3265513915532166462", + "44340419733782462139542985296", + "66414480959112698750297123644", + "850552675034859821", + "67193220221807998597438128015", + "1351326525452201348966937249", + "3309042434648906282", + "47223058899226202495269975973", + "61839078776103743105840656497", + "3031668110259140746", + "69955901086044416766359433744", + "51662538479737930236311918615", + "2556076622750065890", + "40421902471795759921799615216", + "32525476274880580449796382729", + "1838950260820012761", + "9380587020536175024386624408", + "74786565366212577322940026388", + "1786910727711548029", + "45428513335331013862454408726", + "24407141203563864437212043019", + "2878223441876659653", + "777084034635914299331800026501705738592297095264232187921541929654258818226", + "12", + "43514200900089465463492480018", + "74500304272601189716670506598", + "2415363990008974128", + "0", + "2020802182458954660939025977", + "77769176082473988846188219525", + "2598691238676789210", + "0", + "340282366920938463466484327789170949766", + "35063529074838312", + "8875326233450326402", + "340282366920938463466359106799116414895" +] \ No newline at end of file diff --git a/garaga-calldata-tests/fixtures/bn254/proof.json b/garaga-calldata-tests/fixtures/bn254/proof.json new file mode 100644 index 000000000..c551a7b43 --- /dev/null +++ b/garaga-calldata-tests/fixtures/bn254/proof.json @@ -0,0 +1,28 @@ +{ + "pi_a": [ + "16867095230114469303111269582801754677348924111782514818746093562477643731718", + "20212722335582718902672982589607764312189339603046913281774669180256203100136", + "1" + ], + "pi_b": [ + [ + "12758685536372388449510929615906811839459760160946896050208195496890210504448", + "17855758041968043219081456864094552349379559551194469443938085607012057050413" + ], + [ + "13955825016276204826390255402887489684619114124020822491524581785493735884723", + "4753473547991654414764256423822769241872233406220219643335981552335370273842" + ], + [ + "1", + "0" + ] + ], + "pi_c": [ + "671762906748438705619751301153263621349258242033442893897067744180576955019", + "15774728702167052591009228304182510598553322825902260825229935303814649441886", + "1" + ], + "protocol": "groth16", + "curve": "bn128" +} diff --git a/garaga-calldata-tests/fixtures/bn254/public.json b/garaga-calldata-tests/fixtures/bn254/public.json new file mode 100644 index 000000000..4344975bb --- /dev/null +++ b/garaga-calldata-tests/fixtures/bn254/public.json @@ -0,0 +1,3 @@ +[ + "4949495449574848545353525153565755490000" +] diff --git a/garaga-calldata-tests/fixtures/bn254/verification_key.json b/garaga-calldata-tests/fixtures/bn254/verification_key.json new file mode 100644 index 000000000..24dd82811 --- /dev/null +++ b/garaga-calldata-tests/fixtures/bn254/verification_key.json @@ -0,0 +1,94 @@ +{ + "protocol": "groth16", + "curve": "bn128", + "nPublic": 1, + "vk_alpha_1": [ + "20491192805390485299153009773594534940189261866228447918068658471970481763042", + "9383485363053290200918347156157836566562967994039712273449902621266178545958", + "1" + ], + "vk_beta_2": [ + [ + "6375614351688725206403948262868962793625744043794305715222011528459656738731", + "4252822878758300859123897981450591353533073413197771768651442665752259397132" + ], + [ + "10505242626370262277552901082094356697409835680220590971873171140371331206856", + "21847035105528745403288232691147584728191162732299865338377159692350059136679" + ], + [ + "1", + "0" + ] + ], + "vk_gamma_2": [ + [ + "10857046999023057135944570762232829481370756359578518086990519993285655852781", + "11559732032986387107991004021392285783925812861821192530917403151452391805634" + ], + [ + "8495653923123431417604973247489272438418190587263600148770280649306958101930", + "4082367875863433681332203403145435568316851327593401208105741076214120093531" + ], + [ + "1", + "0" + ] + ], + "vk_delta_2": [ + [ + "10857046999023057135944570762232829481370756359578518086990519993285655852781", + "11559732032986387107991004021392285783925812861821192530917403151452391805634" + ], + [ + "8495653923123431417604973247489272438418190587263600148770280649306958101930", + "4082367875863433681332203403145435568316851327593401208105741076214120093531" + ], + [ + "1", + "0" + ] + ], + "vk_alphabeta_12": [ + [ + [ + "2029413683389138792403550203267699914886160938906632433982220835551125967885", + "21072700047562757817161031222997517981543347628379360635925549008442030252106" + ], + [ + "5940354580057074848093997050200682056184807770593307860589430076672439820312", + "12156638873931618554171829126792193045421052652279363021382169897324752428276" + ], + [ + "7898200236362823042373859371574133993780991612861777490112507062703164551277", + "7074218545237549455313236346927434013100842096812539264420499035217050630853" + ] + ], + [ + [ + "7077479683546002997211712695946002074877511277312570035766170199895071832130", + "10093483419865920389913245021038182291233451549023025229112148274109565435465" + ], + [ + "4595479056700221319381530156280926371456704509942304414423590385166031118820", + "19831328484489333784475432780421641293929726139240675179672856274388269393268" + ], + [ + "11934129596455521040620786944827826205713621633706285934057045369193958244500", + "8037395052364110730298837004334506829870972346962140206007064471173334027475" + ] + ] + ], + "IC": [ + [ + "3230230166848506278169341429844025995277520944155248223069557471517720414099", + "13103770257244981396389858672913686503786254567452595604017418062281627967708", + "1" + ], + [ + "19371697418061315618343891460787183627139127309393053314424436252400705071207", + "9445383417235588302514232777371752216736256846043789115945856987874292878586", + "1" + ] + ] +} diff --git a/garaga-calldata-tests/src/bin/gen_garaga_calldata_fixture.rs b/garaga-calldata-tests/src/bin/gen_garaga_calldata_fixture.rs new file mode 100644 index 000000000..b9cc3b40e --- /dev/null +++ b/garaga-calldata-tests/src/bin/gen_garaga_calldata_fixture.rs @@ -0,0 +1,79 @@ +//! Generate `expected_garaga_calldata.json` from fixtures via generate_circom_groth16_garaga_calldata. +//! +//! Usage: +//! cargo run -p garaga-calldata-tests --bin gen-garaga-calldata-fixture + +use garaga_calldata_tests::{ + generate_circom_groth16_garaga_calldata, CircomProof, CircomProofResult, G1, G2, +}; +use serde::Deserialize; +use std::fs; +use std::path::{Path, PathBuf}; + +#[derive(Debug, Deserialize)] +struct FixtureProof { + pi_a: Vec, + pi_b: Vec>, + pi_c: Vec, + protocol: String, + curve: String, +} + +fn load_proof_result(fixture_dir: &Path) -> CircomProofResult { + let proof: FixtureProof = + serde_json::from_str(&fs::read_to_string(fixture_dir.join("proof.json")).expect("proof")) + .expect("parse proof"); + let inputs: Vec = + serde_json::from_str(&fs::read_to_string(fixture_dir.join("public.json")).expect("public")) + .expect("parse public"); + + CircomProofResult { + proof: CircomProof { + a: G1 { + x: proof.pi_a[0].clone(), + y: proof.pi_a[1].clone(), + z: proof + .pi_a + .get(2) + .cloned() + .unwrap_or_else(|| "1".to_string()), + }, + b: G2 { + x: proof.pi_b[0].clone(), + y: proof.pi_b[1].clone(), + z: proof + .pi_b + .get(2) + .cloned() + .unwrap_or_else(|| vec!["1".to_string(), "0".to_string()]), + }, + c: G1 { + x: proof.pi_c[0].clone(), + y: proof.pi_c[1].clone(), + z: proof + .pi_c + .get(2) + .cloned() + .unwrap_or_else(|| "1".to_string()), + }, + protocol: proof.protocol, + curve: proof.curve, + }, + inputs, + } +} + +fn main() { + let fixture_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures/bn254"); + let vk = + fs::read_to_string(fixture_dir.join("verification_key.json")).expect("verification_key"); + let proof_result = load_proof_result(&fixture_dir); + + let calldata = + generate_circom_groth16_garaga_calldata(proof_result, vk).expect("generate calldata"); + + let out = fixture_dir.join("expected_garaga_calldata.json"); + let json = serde_json::to_string_pretty(&calldata).expect("serialize calldata"); + fs::write(&out, json).expect("write expected_garaga_calldata.json"); + println!("Wrote {} felts to {}", calldata.len(), out.display()); +} diff --git a/garaga-calldata-tests/src/circom/mod.rs b/garaga-calldata-tests/src/circom/mod.rs new file mode 100644 index 000000000..9f8831306 --- /dev/null +++ b/garaga-calldata-tests/src/circom/mod.rs @@ -0,0 +1,37 @@ +#[derive(Debug, Clone)] +pub struct G1 { + pub x: String, + pub y: String, + pub z: String, +} + +#[derive(Debug, Clone)] +pub struct G2 { + pub x: Vec, + pub y: Vec, + pub z: Vec, +} + +#[derive(Debug, Clone)] +pub struct CircomProof { + pub a: G1, + pub b: G2, + pub c: G1, + pub protocol: String, + pub curve: String, +} + +#[derive(Debug, Clone)] +pub struct CircomProofResult { + pub proof: CircomProof, + pub inputs: Vec, +} + +#[path = "../../../cli/src/template/init/src/circom/circom_garaga.rs"] +pub mod circom_garaga; +#[path = "../../../cli/src/template/init/src/circom/garaga_convert.rs"] +pub mod garaga_convert; +#[path = "../../../cli/src/template/init/src/circom/snarkjs_types.rs"] +pub mod snarkjs_types; + +pub use circom_garaga::generate_circom_groth16_garaga_calldata; diff --git a/garaga-calldata-tests/src/lib.rs b/garaga-calldata-tests/src/lib.rs new file mode 100644 index 000000000..6577f85d3 --- /dev/null +++ b/garaga-calldata-tests/src/lib.rs @@ -0,0 +1,215 @@ +//! Integration tests for Circom/Groth16 Garaga calldata helpers in the CLI template. + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum MoproError { + #[error("CircomError: {0}")] + CircomError(String), +} + +mod circom; + +pub use circom::{generate_circom_groth16_garaga_calldata, CircomProof, CircomProofResult, G1, G2}; + +#[cfg(test)] +mod tests { + use super::*; + use circom::garaga_convert::{ + parse_biguint, public_inputs_to_biguint, to_groth16_proof_from_mopro, to_groth16_vk, + }; + use circom::snarkjs_types::parse_snarkjs_vk_json; + use circom::{CircomProof, CircomProofResult, G1, G2}; + use num_bigint::BigUint; + use serde::Deserialize; + + /// Test-only: load SnarkJS `proof.json` fixtures into a [`CircomProof`]. + #[derive(Debug, Deserialize)] + struct FixtureProof { + pi_a: Vec, + pi_b: Vec>, + pi_c: Vec, + protocol: String, + curve: String, + } + + fn fixture_dir() -> std::path::PathBuf { + std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("fixtures/bn254") + } + + fn read_fixture(name: &str) -> String { + std::fs::read_to_string(fixture_dir().join(name)).unwrap() + } + + fn load_fixture_proof_result() -> CircomProofResult { + let proof: FixtureProof = serde_json::from_str(&read_fixture("proof.json")).unwrap(); + let inputs: Vec = serde_json::from_str(&read_fixture("public.json")).unwrap(); + CircomProofResult { + proof: CircomProof { + a: G1 { + x: proof.pi_a[0].clone(), + y: proof.pi_a[1].clone(), + z: proof + .pi_a + .get(2) + .cloned() + .unwrap_or_else(|| "1".to_string()), + }, + b: G2 { + x: proof.pi_b[0].clone(), + y: proof.pi_b[1].clone(), + z: proof + .pi_b + .get(2) + .cloned() + .unwrap_or_else(|| vec!["1".to_string(), "0".to_string()]), + }, + c: G1 { + x: proof.pi_c[0].clone(), + y: proof.pi_c[1].clone(), + z: proof + .pi_c + .get(2) + .cloned() + .unwrap_or_else(|| "1".to_string()), + }, + protocol: proof.protocol, + curve: proof.curve, + }, + inputs, + } + } + + #[test] + fn test_parse_snarkjs_vk_json_valid() { + let vk = parse_snarkjs_vk_json(&read_fixture("verification_key.json")).unwrap(); + assert_eq!(vk.ic.len(), vk.n_public + 1); + } + + /// BN254 scalar-field order (Fr), decimal. + fn bn254_scalar_field() -> BigUint { + BigUint::parse_bytes( + b"21888242871839275222246405745257275088548364400416034343698204186575808495617", + 10, + ) + .unwrap() + } + + /// BN254 base-field modulus (Fq), decimal. + fn bn254_base_field() -> BigUint { + BigUint::parse_bytes( + b"21888242871839275222246405745257275088696311157297823662689037894645226208583", + 10, + ) + .unwrap() + } + + #[test] + fn test_garaga_convert_bn254_from_mopro_fixtures() { + let proof_result = load_fixture_proof_result(); + let vk = parse_snarkjs_vk_json(&read_fixture("verification_key.json")).unwrap(); + + let garaga_proof = to_groth16_proof_from_mopro( + &proof_result.proof.a.x, + &proof_result.proof.a.y, + &proof_result.proof.b.x, + &proof_result.proof.b.y, + &proof_result.proof.c.x, + &proof_result.proof.c.y, + &proof_result.inputs, + ) + .unwrap(); + assert_eq!( + garaga_proof.a.x.to_string(), + "16867095230114469303111269582801754677348924111782514818746093562477643731718" + ); + + let garaga_vk = to_groth16_vk(&vk).unwrap(); + assert_eq!(garaga_vk.ic.len(), vk.n_public + 1); + } + + #[test] + fn test_parse_biguint_rejects_outside_base_field() { + let outside = bn254_base_field().to_string(); + let err = parse_biguint(&outside).unwrap_err(); + assert!(err.contains("outside BN254 base field")); + } + + #[test] + fn test_parse_biguint_preserves_decimal_parse_errors() { + let err = parse_biguint("not-a-number").unwrap_err(); + assert!(err.starts_with("invalid coordinate 'not-a-number':")); + } + + #[test] + fn test_public_inputs_to_biguint_rejects_outside_scalar_field() { + let outside = bn254_scalar_field().to_string(); + let err = public_inputs_to_biguint(std::slice::from_ref(&outside)).unwrap_err(); + assert!(err.contains("outside BN254 scalar field")); + assert!(err.contains(&outside)); + } + + #[test] + fn test_public_inputs_to_biguint_preserves_decimal_parse_errors() { + let err = public_inputs_to_biguint(&["not-a-number".to_string()]).unwrap_err(); + assert!(err.starts_with("invalid coordinate 'not-a-number':")); + } + + #[test] + fn test_public_inputs_to_biguint_allows_empty() { + let converted = public_inputs_to_biguint(&[]).unwrap(); + assert!(converted.is_empty()); + } + + #[test] + fn test_public_inputs_match_serialized_vec() { + let inputs: Vec = serde_json::from_str(&read_fixture("public.json")).unwrap(); + let round_trip: Vec = + serde_json::from_str(&serde_json::to_string(&inputs).unwrap()).unwrap(); + assert_eq!(inputs, round_trip); + } + + #[test] + fn test_generate_circom_groth16_garaga_calldata_bn254_golden() { + let proof_result = load_fixture_proof_result(); + let vk = read_fixture("verification_key.json"); + let expected: Vec = + serde_json::from_str(&read_fixture("expected_garaga_calldata.json")).unwrap(); + + let got = generate_circom_groth16_garaga_calldata(proof_result, vk).unwrap(); + assert_eq!(got, expected); + assert_eq!(got.len(), 1936); + assert_eq!(got[0], "1935"); + } + + #[test] + fn test_generate_circom_groth16_garaga_calldata_rejects_oversized_public_inputs() { + let mut proof_result = load_fixture_proof_result(); + proof_result.inputs.push("0".to_string()); + let vk = read_fixture("verification_key.json"); + + let err = generate_circom_groth16_garaga_calldata(proof_result, vk).unwrap_err(); + match err { + MoproError::CircomError(msg) => { + assert!(msg.contains("public input count mismatch")); + } + } + } + + #[test] + fn test_generate_circom_groth16_garaga_calldata_rejects_public_input_outside_scalar_field() { + let mut proof_result = load_fixture_proof_result(); + let outside = bn254_scalar_field().to_string(); + proof_result.inputs = vec![outside.clone()]; + let vk = read_fixture("verification_key.json"); + + let err = generate_circom_groth16_garaga_calldata(proof_result, vk).unwrap_err(); + match err { + MoproError::CircomError(msg) => { + assert!(msg.contains("outside BN254 scalar field")); + assert!(msg.contains(&outside)); + } + } + } +}