From 1166d66df01fe8ae4aaab9e90c8bcf56de952b43 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Thu, 19 Oct 2023 11:01:11 +0200 Subject: [PATCH 01/21] feat: replace ark-groth16 from 0.3.0 to 0.4.0 to make buildable and testable --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 11a37363..0722bcd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ ark-crypto-primitives = {version = "0.4.0", features = ["sponge","r1cs","snark"] ark-r1cs-std = { version = "0.4.0", default-features = false } ark-relations = { version = "0.4.0", default-features = false, optional = true } ark-snark = { version = "0.4.0", default-features = false } -ark-groth16 = { version = "0.3.0" } +ark-groth16 = { version = "0.4.0" } ark-bw6-761 = { version = "0.4.0" } ark-poly-commit = { version = "0.4.0" } ark-poly = {version = "0.4.0"} From 246591f59a51b5d80074afcf1a2ee9040ff9bb94 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Sat, 4 Nov 2023 16:49:00 +0100 Subject: [PATCH 02/21] feat: start writing circuit for pst-mipp and create new struct for poseidon transcript --- src/constraints.rs | 136 +++++++++++++++++++++++++++++++++++-- src/poseidon_transcript.rs | 4 +- 2 files changed, 132 insertions(+), 8 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 931d3f0e..63693158 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,26 +1,56 @@ use ark_ec::pairing::Pairing; -use std::borrow::Borrow; - +use std::{borrow::Borrow, marker::PhantomData}; +use ark_r1cs_std::prelude::*; use crate::{ math::Math, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, + poseidon_transcript::PoseidonTranscript, }; - +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use crate::ark_std::One; +use crate::mipp::MippProof; use ark_ff::PrimeField; - +use ark_ff::BigInteger; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; -use ark_poly_commit::multilinear_pc::data_structures::Commitment; +use ark_poly_commit::multilinear_pc::{ + data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, + MultilinearPC, +}; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, fields::fp::FpVar, prelude::{EqGadget, FieldVar}, + }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; - +pub struct PoseidonTranscripVar2 +where +E: Pairing, +IV: PairingVar, +{ + pub cs: ConstraintSystemRef<::BaseField>, + pub sponge: PoseidonSpongeVar<::BaseField>, + _iv: PhantomData, +} +impl PoseidonTranscripVar2 +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::G1Var: AbsorbGadget<::BaseField>, +{ + fn new(cs: ConstraintSystemRef<::BaseField>, params: &PoseidonConfig<::BaseField>) -> Self { + let mut sponge = PoseidonSpongeVar::new(cs.clone(), params); + Self { cs, sponge, _iv: PhantomData} + } + fn append(&mut self, input: IV::G1Var) -> Result<(), SynthesisError> { + self.sponge.absorb(&input) + } +} pub struct PoseidonTranscripVar where F: PrimeField, @@ -477,3 +507,97 @@ pub struct VerifierConfig { // Ok(()) // } // } +struct MippTUVar +where + E:Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar +{ + tc: IV::GTVar, + uc: IV::G1Var, +} +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + transcript: PoseidonTranscript, + vk: VerifierKey, + U: Commitment, + point: Vec, + v: E::ScalarField, + pst_proof: Proof, + mipp_proof: MippProof, + T: E::TargetField, + _iv: PhantomData, +} +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, +{ + fn generate_constraints( + self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + + // allocate point + let mut point_var = Vec::new(); + for p in self.point.clone().into_iter() { + let scalar_in_fq = + &E::BaseField::from_bigint(::BigInt::from_bits_le( + p.into_bigint().to_bits_le().as_slice(), + )) + .unwrap(); + let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + point_var.push(p_var); + } + let len = point_var.len(); + let odd = if len % 2 == 1 { 1 } else { 0 }; + let a_var = &point_var[0..len / 2 + odd]; + let b_var = &point_var[len / 2 + odd..len]; + + // start mipp verify + // start allocate struct mipp proof + // allocate comms_u + let mut comms_u_var = Vec::new(); + for (first,second) in self.mipp_proof.comms_u.clone().into_iter() { + let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; + comms_u_var.push((first_var,second_var)); + } + // allocate comms_t + let mut comms_t_var = Vec::new(); + for (first,second) in self.mipp_proof.comms_t.clone().into_iter() { + let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; + comms_t_var.push((first_var,second_var)); + } + + let mut xs = Vec::new(); + let mut xs_inv = Vec::new(); + let mut final_y = E::ScalarField::one(); + + // start allocate T + let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; + // start allocate U.g_product + let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; + + let final_res_var = MippTUVar { + tc: T_var.clone(), + uc: U_g_product_var, + }; + + // create transcriptVar from transcript + let params = self.transcript.params; + let transcript_var = PoseidonTranscripVar2::new(cs.clone(), ¶ms); + + transcript_var.append(U_g_product_var); + + Ok(()) + } +} \ No newline at end of file diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index 8a08ae7e..f1c7a71c 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -10,8 +10,8 @@ use ark_serialize::Compress; #[derive(Clone)] /// TODO pub struct PoseidonTranscript { - sponge: PoseidonSponge, - params: PoseidonConfig, + pub sponge: PoseidonSponge, + pub params: PoseidonConfig, } impl Transcript for PoseidonTranscript { From 5c2b0d13e3975ec484a0a7e3b1712de606d36628 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Thu, 9 Nov 2023 14:28:30 +0100 Subject: [PATCH 03/21] feat: add parse poseidon config from ScalarField to BaseField --- src/constraints.rs | 64 +++++++++++++++++++++++++++++------ src/parameters.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 11 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 63693158..ec9af5d9 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,12 +1,14 @@ use ark_ec::pairing::Pairing; use std::{borrow::Borrow, marker::PhantomData}; use ark_r1cs_std::prelude::*; +use crate::parameters::params_to_base_field; use crate::{ math::Math, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, poseidon_transcript::PoseidonTranscript, }; +use crate::parameters::get_bls12377_fq_params; use ark_crypto_primitives::sponge::constraints::AbsorbGadget; use crate::ark_std::One; use crate::mipp::MippProof; @@ -43,13 +45,10 @@ where IV::G1Var: CurveVar, IV::G1Var: AbsorbGadget<::BaseField>, { - fn new(cs: ConstraintSystemRef<::BaseField>, params: &PoseidonConfig<::BaseField>) -> Self { - let mut sponge = PoseidonSpongeVar::new(cs.clone(), params); + fn new(cs: ConstraintSystemRef<::BaseField>, t: &PoseidonTranscript<::BaseField>) -> Self { + let mut sponge = PoseidonSpongeVar::new(cs.clone(), &t.params); Self { cs, sponge, _iv: PhantomData} } - fn append(&mut self, input: IV::G1Var) -> Result<(), SynthesisError> { - self.sponge.absorb(&input) - } } pub struct PoseidonTranscripVar where @@ -587,17 +586,60 @@ where // start allocate U.g_product let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; - let final_res_var = MippTUVar { + let final_res_var: MippTUVar = MippTUVar { tc: T_var.clone(), uc: U_g_product_var, }; + // let scalar_in_fq = + // &E::BaseField::from_bigint(::BigInt::from_bits_le( + // p.into_bigint().to_bits_le().as_slice(), + // )) + // .unwrap(); + + let params: PoseidonConfig = params_to_base_field(self.transcript.params); + let mut sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms); + // let element = params[1][2]; + // let scalar_in_fq = + // &E::BaseField::from_bigint(::BigInt::from_bits_le( + // element.into_bigint().to_bits_le().as_slice(), + // )) + // .unwrap(); + // let params2 = vec![]; + // for inner_vec in ¶ms { + // let p2 = vec![]; + // for &element in inner_vec { + // let scalar_in_fq = + // &E::BaseField::from_bigint(::BigInt::from_bits_le( + // element.into_bigint().to_bits_le().as_slice(), + // )) + // .unwrap(); + // p2.push(scalar_in_fq); + // } + // params2.push(p2); + // }x + // self.transcript.params.ark = params2; + //let prova = PoseidonConfig::new(1,2,3,vec![vec![scalar_in_fq]],vec![vec![scalar_in_fq]]4,5); // create transcriptVar from transcript - let params = self.transcript.params; - let transcript_var = PoseidonTranscripVar2::new(cs.clone(), ¶ms); - - transcript_var.append(U_g_product_var); - + // let mut sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms); + // let transcript_var: PoseidonTranscripVar2 = PoseidonTranscripVar2::new(cs.clone(), &self.transcript); + + // transcript_var.append(U_g_product_var); + + // for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { + // let (comm_u_l, comm_u_r) = comm_u; + // let (comm_t_l, comm_t_r) = comm_t; + // // Fiat-Shamir challenge + // transcript_var.append(comm_u_l); + // transcript_var.append(comm_u_r); + // transcript_var.append(comm_t_l); + // transcript_var.append(comm_t_r); + // let c_inv_var = transcript_var.challenge()?; + // let c_var = c_inv_var.inverse().unwrap(); + + // xs.push(c_var); + // xs_inv.push(c_inv_var); + // } Ok(()) } } \ No newline at end of file diff --git a/src/parameters.rs b/src/parameters.rs index ce5b5a66..0d766469 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -1,6 +1,15 @@ use ark_bls12_377::Fr; +use ark_bls12_377::Fq; use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +use ark_ec::pairing::Pairing; +use ark_ff::BigInt; +use std::fmt::Debug; use std::str::FromStr; +use ark_ff::PrimeField; +use poseidon_parameters::PoseidonParameters; +use ark_ff::BigInteger; +use crate::ark_std::One; +use ark_ff::BigInteger64; // Copyright: https://github.com/nikkolasg/ark-dkg/blob/main/src/parameters.rs use json::JsonValue; use lazy_static::lazy_static; @@ -175,6 +184,80 @@ pub fn poseidon_params() -> PoseidonConfig { ) } +// +pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig +where +E: Pairing, +{ + let ark = FR["ark"] + .members() + .map(|ark| { + ark + .members() + .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) + .collect::>() + }) + .collect::>(); + + let md5 = FR["md5"] + .members() + .map(|ark| { + ark + .members() + .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) + .collect::>() + }) + .collect::>(); + + PoseidonConfig::new( + FR["full_rounds"].as_usize().unwrap(), + FR["partial_rounds"].as_usize().unwrap(), + FR["alpha"].as_u64().unwrap(), + md5, + ark, + FR["rate"].as_usize().unwrap(), + // TODO (nikkolasg): check out the concrete parameters for the capacity + // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 + 1, + ) +} +fn str_to_bits(input_str: &str) -> Vec { + input_str + .chars() + .flat_map(|c| (0..8).map(move |i| (c as u8 & (1 << (7 - i))) != 0)) + .collect() +} + +pub fn get_bls12377_fq_params() -> PoseidonConfig { + let arks = FR["ark"] + .members() + .map(|ark| { + ark.members() + .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); + let mds = FR["mds"] + .members() + .map(|m| { + m.members() + .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); + PoseidonConfig::new( + FR["full_rounds"].as_usize().unwrap(), + FR["partial_rounds"].as_usize().unwrap(), + FR["alpha"].as_u64().unwrap(), + mds, + arks, + FR["rate"].as_usize().unwrap(), + // TODO (nikkolasg): check out the concrete parameters for the capacity + // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 + 1, + ) +} + // Generated from poseidon_transcript::test::poseidon_parameters_generation pub fn poseidon_params_bls12381() -> PoseidonConfig { use ark_ff::PrimeField; From 4020529f636e7f1719ada5ba33820bb15f2bc900 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Thu, 9 Nov 2023 14:52:16 +0100 Subject: [PATCH 04/21] feat: add absorb and challange --- src/constraints.rs | 73 +++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 50 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index ec9af5d9..5631649b 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -538,6 +538,8 @@ where IV::G1Var: CurveVar, IV::G2Var: CurveVar, IV::GTVar: FieldVar, + IV::G1Var: AbsorbGadget, + IV::GTVar: AbsorbGadget, { fn generate_constraints( self, @@ -588,58 +590,29 @@ where let final_res_var: MippTUVar = MippTUVar { tc: T_var.clone(), - uc: U_g_product_var, + uc: U_g_product_var.clone(), }; - // let scalar_in_fq = - // &E::BaseField::from_bigint(::BigInt::from_bits_le( - // p.into_bigint().to_bits_le().as_slice(), - // )) - // .unwrap(); - - let params: PoseidonConfig = params_to_base_field(self.transcript.params); - let mut sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms); - // let element = params[1][2]; - // let scalar_in_fq = - // &E::BaseField::from_bigint(::BigInt::from_bits_le( - // element.into_bigint().to_bits_le().as_slice(), - // )) - // .unwrap(); - // let params2 = vec![]; - // for inner_vec in ¶ms { - // let p2 = vec![]; - // for &element in inner_vec { - // let scalar_in_fq = - // &E::BaseField::from_bigint(::BigInt::from_bits_le( - // element.into_bigint().to_bits_le().as_slice(), - // )) - // .unwrap(); - // p2.push(scalar_in_fq); - // } - // params2.push(p2); - // }x - // self.transcript.params.ark = params2; - //let prova = PoseidonConfig::new(1,2,3,vec![vec![scalar_in_fq]],vec![vec![scalar_in_fq]]4,5); - // create transcriptVar from transcript - // let mut sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms); - // let transcript_var: PoseidonTranscripVar2 = PoseidonTranscripVar2::new(cs.clone(), &self.transcript); - - // transcript_var.append(U_g_product_var); - - // for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { - // let (comm_u_l, comm_u_r) = comm_u; - // let (comm_t_l, comm_t_r) = comm_t; - // // Fiat-Shamir challenge - // transcript_var.append(comm_u_l); - // transcript_var.append(comm_u_r); - // transcript_var.append(comm_t_l); - // transcript_var.append(comm_t_r); - // let c_inv_var = transcript_var.challenge()?; - // let c_var = c_inv_var.inverse().unwrap(); - - // xs.push(c_var); - // xs_inv.push(c_inv_var); - // } + let params: PoseidonConfig = params_to_base_field::(self.transcript.params); + let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); + transcript_var.absorb(&U_g_product_var); + + for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { + let (comm_u_l, comm_u_r) = comm_u; + let (comm_t_l, comm_t_r) = comm_t; + // Fiat-Shamir challenge + transcript_var.absorb(comm_u_l); + transcript_var.absorb(comm_u_r); + transcript_var.absorb(comm_t_l); + transcript_var.absorb(comm_t_r); + let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + let c_var = c_inv_var.inverse().unwrap(); + + xs.push(c_var); + xs_inv.push(c_inv_var); + + } + Ok(()) } } \ No newline at end of file From 8f4f91e893cf2c9edf6c6fccf6bfd46e129141bc Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Fri, 10 Nov 2023 12:42:03 +0100 Subject: [PATCH 05/21] feat: added part of the circuit (delete reduce and par_iter) --- src/constraints.rs | 86 ++++++++++++++++++++++++++++++++++++++++++---- src/parameters.rs | 83 +++++++++++++++++++++++++++++++------------- 2 files changed, 140 insertions(+), 29 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 5631649b..928cccdc 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,4 +1,8 @@ use ark_ec::pairing::Pairing; +use ark_r1cs_std::groups::bls12::G1Var; + +use std::ops::MulAssign; +use std::ops::AddAssign; use std::{borrow::Borrow, marker::PhantomData}; use ark_r1cs_std::prelude::*; use crate::parameters::params_to_base_field; @@ -18,6 +22,7 @@ use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; +use std::ops::Mul; use ark_poly_commit::multilinear_pc::{ data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, MultilinearPC, @@ -513,9 +518,37 @@ where IV::G1Var: CurveVar, IV::GTVar: FieldVar { - tc: IV::GTVar, - uc: IV::G1Var, + pub tc: IV::GTVar, + pub uc: IV::G1Var, +} + +impl Default for MippTUVar +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar +{ + fn default() -> Self { + Self { + tc: IV::GTVar::one(), + uc: IV::G1Var::zero(), + } + } +} +impl MippTUVar +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar +{ + fn merge(&mut self, other: &Self) { + self.tc.mul_assign(&other.tc); + self.uc.add_assign(&other.uc); + } } + struct TestudoCommVerifier where E: Pairing, @@ -581,7 +614,8 @@ where let mut xs = Vec::new(); let mut xs_inv = Vec::new(); - let mut final_y = E::ScalarField::one(); + let mut final_y = E::BaseField::one(); + let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; // start allocate T let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; @@ -593,6 +627,7 @@ where uc: U_g_product_var.clone(), }; + let params: PoseidonConfig = params_to_base_field::(self.transcript.params); let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); transcript_var.absorb(&U_g_product_var); @@ -608,11 +643,50 @@ where let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); let c_var = c_inv_var.inverse().unwrap(); - xs.push(c_var); - xs_inv.push(c_inv_var); - + xs.push(c_var.clone()); + xs_inv.push(c_inv_var.clone()); + + let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; + } + + enum Op<'a, E: Pairing, IV: PairingVar> { + TC(&'a IV::GTVar, FpVar< ::BaseField >), + UC(&'a IV::G1Var, &'a FpVar< ::BaseField >), } + let res = comms_t_var + .iter() + .zip(comms_u_var.iter()) + .zip(xs.iter().zip(xs_inv.iter())) + .flat_map(|((comm_t, comm_u), (c, c_inv))| { + let (comm_t_l, comm_t_r) = comm_t; + let (comm_u_l, comm_u_r) = comm_u; + + // we multiple left side by x^-1 and right side by x + vec![ + Op::TC(comm_t_l, c_inv.clone()), + Op::TC(comm_t_r, c.clone()), + Op::UC(comm_u_l, c_inv), + Op::UC(comm_u_r, c), + ] + }) + .fold(MippTUVar::::default() , |mut res, op: Op| { + match op { + Op::TC(tx, c) => { + // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; + let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); + res.tc.mul_assign(&tx); + } + Op::UC(zx, c) => { + let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); + res.uc.add_assign(&uxp); + } + } + res + }); + + Ok(()) } } \ No newline at end of file diff --git a/src/parameters.rs b/src/parameters.rs index 0d766469..09c97d79 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -185,26 +185,70 @@ pub fn poseidon_params() -> PoseidonConfig { } // +// pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig +// where +// E: Pairing, +// { +// let ark = FR["ark"] +// .members() +// .map(|ark| { +// ark +// .members() +// .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) +// .collect::>() +// }) +// .collect::>(); + +// let md5 = FR["md5"] +// .members() +// .map(|ark| { +// ark +// .members() +// .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) +// .collect::>() +// }) +// .collect::>(); + +// PoseidonConfig::new( +// FR["full_rounds"].as_usize().unwrap(), +// FR["partial_rounds"].as_usize().unwrap(), +// FR["alpha"].as_u64().unwrap(), +// md5, +// ark, +// FR["rate"].as_usize().unwrap(), +// // TODO (nikkolasg): check out the concrete parameters for the capacity +// // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 +// 1, +// ) +// } +// fn str_to_bits(input_str: &str) -> Vec { +// input_str +// .chars() +// .flat_map(|c| (0..8).map(move |i| (c as u8 & (1 << (7 - i))) != 0)) +// .collect() +// } + pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig where E: Pairing, { - let ark = FR["ark"] - .members() - .map(|ark| { - ark - .members() - .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) - .collect::>() - }) - .collect::>(); + let arks = FR["ark"] + .members() + .map(|ark| { + ark + .members() + .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) + .map(|v| E::BaseField::from_bigint(::BigInt::from_bits_le( v.into_bigint().to_bits_le().as_slice())).unwrap()) + .collect::>() + }) + .collect::>(); - let md5 = FR["md5"] + let mds = FR["mds"] .members() - .map(|ark| { - ark - .members() - .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) + .map(|m| { + m.members() + .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) + .map(|v| E::BaseField::from_bigint(::BigInt::from_bits_le( v.into_bigint().to_bits_le().as_slice())).unwrap()) .collect::>() }) .collect::>(); @@ -213,21 +257,14 @@ E: Pairing, FR["full_rounds"].as_usize().unwrap(), FR["partial_rounds"].as_usize().unwrap(), FR["alpha"].as_u64().unwrap(), - md5, - ark, + mds, + arks, FR["rate"].as_usize().unwrap(), // TODO (nikkolasg): check out the concrete parameters for the capacity // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 1, ) } -fn str_to_bits(input_str: &str) -> Vec { - input_str - .chars() - .flat_map(|c| (0..8).map(move |i| (c as u8 & (1 << (7 - i))) != 0)) - .collect() -} - pub fn get_bls12377_fq_params() -> PoseidonConfig { let arks = FR["ark"] .members() From f170f2a0de18a4c5dbb237472d8b927511838a6f Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Fri, 10 Nov 2023 14:56:03 +0100 Subject: [PATCH 06/21] feat: start write check2 verify pst as circuit --- src/constraints.rs | 61 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 928cccdc..a72ed68f 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,6 +1,7 @@ use ark_ec::pairing::Pairing; use ark_r1cs_std::groups::bls12::G1Var; - +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; use std::ops::MulAssign; use std::ops::AddAssign; use std::{borrow::Borrow, marker::PhantomData}; @@ -548,6 +549,12 @@ where self.uc.add_assign(&other.uc); } } +pub struct CommitmentG2Var> { + /// number of variables + pub nv: usize, + /// product of g as described by the vRAM paper + pub h_product: IV::G2Var, +} struct TestudoCommVerifier where @@ -622,7 +629,7 @@ where // start allocate U.g_product let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; - let final_res_var: MippTUVar = MippTUVar { + let mut final_res_var: MippTUVar = MippTUVar { tc: T_var.clone(), uc: U_g_product_var.clone(), }; @@ -655,7 +662,7 @@ where UC(&'a IV::G1Var, &'a FpVar< ::BaseField >), } - let res = comms_t_var + let res_var = comms_t_var .iter() .zip(comms_u_var.iter()) .zip(xs.iter().zip(xs_inv.iter())) @@ -686,7 +693,55 @@ where res }); + let ref_final_res_var = &mut final_res_var; + ref_final_res_var.merge(&res_var); + + let mut rs: Vec::BaseField>> = Vec::new(); + let m = xs_inv.len(); + for _i in 0..m { + let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + rs.push(r); + } + + let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + + // let rs_var = rs.clone(); + let v_var: FpVar<::BaseField> = (0..m) + .into_iter() + .map(|i| one_var.clone() + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) + .fold(one_var.clone(), |acc, x| acc * x); + + let comm_h = CommitmentG2:: { + nv: m, + h_product: self.mipp_proof.final_h, + }; + let check_h = check_2_gadget::(cs.clone(), self.vk, &comm_h, &rs,v_var, &self.mipp_proof.pst_proof_h); Ok(()) } +} + +fn check_2_gadget>(cs: ConstraintSystemRef, vk: VerifierKey, commitment: &CommitmentG2, point_var: &Vec::BaseField>>, value_var: FpVar<::BaseField>, proof: &ProofG1) -> bool +where +IV::G1Var: CurveVar, +IV::G2Var: CurveVar, +IV::GTVar: FieldVar, +{ + let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g)).unwrap(); + let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h)).unwrap(); + let mut vk_gmask_var = Vec::new(); + for g_mask in vk.g_mask_random.clone().into_iter() { + let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); + vk_gmask_var.push(g_mask_var); + } + // allocate commitment + let com_g2_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product)).unwrap(); + + let pair_right_op = com_g2_prod_var - (vk_h_var.scalar_mul_le(value_var.to_bits_le().unwrap().iter()).unwrap()); + let right_prepared = IV::prepare_g2(&pair_right_op).unwrap(); + let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); + let left = IV::pairing(left_prepared, right_prepared).unwrap(); + + + true } \ No newline at end of file From 2978f806cb575277473ea1589ba34abb15a4b0c3 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Fri, 10 Nov 2023 21:50:48 +0100 Subject: [PATCH 07/21] feat: finish write circuit for check2 --- src/constraints.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index a72ed68f..76c1a0ae 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -2,6 +2,7 @@ use ark_ec::pairing::Pairing; use ark_r1cs_std::groups::bls12::G1Var; use ark_poly_commit::multilinear_pc::data_structures::ProofG1; use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use digest::generic_array::typenum::True; use std::ops::MulAssign; use std::ops::AddAssign; use std::{borrow::Borrow, marker::PhantomData}; @@ -717,6 +718,40 @@ where }; let check_h = check_2_gadget::(cs.clone(), self.vk, &comm_h, &rs,v_var, &self.mipp_proof.pst_proof_h); + assert!(check_h == true); + + let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; + let final_u_var = final_a_var.scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()).unwrap(); + + let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; + + let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); + let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); + + let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); + let check_t; + + if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() + { + check_t = true; + }else{ + check_t = false; + } + assert!(check_t == true); + + let check_u; + if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() + { + check_u = true; + }else{ + check_u = false; + } + assert!(check_u == true); + + let mut a_rev_var = a_var.to_vec().clone(); + a_rev_var.reverse(); + + // MAKE PST CHECKKK Ok(()) } } @@ -742,6 +777,42 @@ IV::GTVar: FieldVar, let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); let left = IV::pairing(left_prepared, right_prepared).unwrap(); - - true + let mut h_mul_var = Vec::new(); + + for p in point_var.into_iter() { + let x = vk_h_var.scalar_mul_le(p.to_bits_le().unwrap().iter()).unwrap(); + h_mul_var.push(x); + } + let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); + let mut h_mask_random_var = Vec::new(); + for h_mask in h_mask_random.clone().into_iter() { + let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask)).unwrap(); + h_mask_random_var.push(h_mask_var); +} + let pairing_rights_var: Vec<_> = (0..vk.nv) + .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) + .collect(); + let pairing_rights_var: Vec = pairing_rights_var + .into_iter() + .map(|p| IV::prepare_g2(&p).unwrap()) + .collect(); + let mut proofs_var = Vec::new(); + for p in proof.proofs.clone().into_iter() { + let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); + proofs_var.push(proof_var); + } + let pairing_lefts_var: Vec = proofs_var + .into_iter() + .map(|p| IV::prepare_g1(&p).unwrap()) + .collect(); + + let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var).unwrap(); + let right = IV::final_exponentiation(&right_ml).unwrap(); + + if () == left.enforce_equal(&right).unwrap() + { + true + }else{ + false + } } \ No newline at end of file From ea4987d91c629bc45a39bbb4db57ccb9ab99141b Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Mon, 13 Nov 2023 17:05:45 +0100 Subject: [PATCH 08/21] feat: finish circuit and write groth16 verifier --- Cargo.toml | 1 + src/constraints.rs | 633 +++++++++++++++++++++++++++++++-------------- src/parameters.rs | 103 ++++---- 3 files changed, 493 insertions(+), 244 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0722bcd2..dbfec1c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ tracing-subscriber = { version = "0.2" } [dev-dependencies] +rand_chacha = { version = "0.3.0", default-features = false } serde = { version = "1.0", features = ["derive"] } csv = "1.1.5" criterion = "0.3.6" diff --git a/src/constraints.rs b/src/constraints.rs index 76c1a0ae..8d7877bb 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,60 +1,68 @@ -use ark_ec::pairing::Pairing; -use ark_r1cs_std::groups::bls12::G1Var; -use ark_poly_commit::multilinear_pc::data_structures::ProofG1; -use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; -use digest::generic_array::typenum::True; -use std::ops::MulAssign; -use std::ops::AddAssign; -use std::{borrow::Borrow, marker::PhantomData}; -use ark_r1cs_std::prelude::*; +use crate::ark_std::One; +use crate::mipp::MippProof; +use crate::parameters::get_bls12377_fq_params; +use ark_serialize::Compress; use crate::parameters::params_to_base_field; use crate::{ math::Math, + poseidon_transcript::PoseidonTranscript, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, - poseidon_transcript::PoseidonTranscript, }; -use crate::parameters::get_bls12377_fq_params; use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use crate::ark_std::One; -use crate::mipp::MippProof; -use ark_ff::PrimeField; -use ark_ff::BigInteger; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; -use std::ops::Mul; +use ark_crypto_primitives::Error; +use ark_ec::pairing::Pairing; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; use ark_poly_commit::multilinear_pc::{ data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, MultilinearPC, }; +use ark_r1cs_std::groups::bls12::G1Var; +use ark_r1cs_std::prelude::*; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, fields::fp::FpVar, prelude::{EqGadget, FieldVar}, - }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; -pub struct PoseidonTranscripVar2 +use digest::generic_array::typenum::True; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::MulAssign; +use std::{borrow::Borrow, marker::PhantomData}; +pub struct PoseidonTranscripVar2 where -E: Pairing, -IV: PairingVar, + E: Pairing, + IV: PairingVar, { pub cs: ConstraintSystemRef<::BaseField>, pub sponge: PoseidonSpongeVar<::BaseField>, _iv: PhantomData, } -impl PoseidonTranscripVar2 +impl PoseidonTranscripVar2 where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, IV::G1Var: AbsorbGadget<::BaseField>, { - fn new(cs: ConstraintSystemRef<::BaseField>, t: &PoseidonTranscript<::BaseField>) -> Self { + fn new( + cs: ConstraintSystemRef<::BaseField>, + t: &PoseidonTranscript<::BaseField>, + ) -> Self { let mut sponge = PoseidonSpongeVar::new(cs.clone(), &t.params); - Self { cs, sponge, _iv: PhantomData} + Self { + cs, + sponge, + _iv: PhantomData, + } } } pub struct PoseidonTranscripVar @@ -513,23 +521,23 @@ pub struct VerifierConfig { // Ok(()) // } // } -struct MippTUVar +struct MippTUVar where - E:Pairing, + E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, - IV::GTVar: FieldVar + IV::GTVar: FieldVar, { pub tc: IV::GTVar, pub uc: IV::G1Var, } -impl Default for MippTUVar +impl Default for MippTUVar where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, - IV::GTVar: FieldVar + IV::GTVar: FieldVar, { fn default() -> Self { Self { @@ -538,12 +546,12 @@ where } } } -impl MippTUVar +impl MippTUVar where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, - IV::GTVar: FieldVar + IV::GTVar: FieldVar, { fn merge(&mut self, other: &Self) { self.tc.mul_assign(&other.tc); @@ -559,111 +567,134 @@ pub struct CommitmentG2Var> { struct TestudoCommVerifier where - E: Pairing, - IV: PairingVar, + E: Pairing, + IV: PairingVar, { - transcript: PoseidonTranscript, - vk: VerifierKey, - U: Commitment, - point: Vec, - v: E::ScalarField, - pst_proof: Proof, - mipp_proof: MippProof, - T: E::TargetField, - _iv: PhantomData, + //transcript: PoseidonTranscript, + vk: VerifierKey, + U: Commitment, + point: Vec, + v: E::ScalarField, + pst_proof: Proof, + mipp_proof: MippProof, + T: E::TargetField, + _iv: PhantomData, } -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +impl Clone for TestudoCommVerifier where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::G2Var: CurveVar, - IV::GTVar: FieldVar, - IV::G1Var: AbsorbGadget, - IV::GTVar: AbsorbGadget, + E: Pairing, + IV: PairingVar, { - fn generate_constraints( - self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - - // allocate point - let mut point_var = Vec::new(); - for p in self.point.clone().into_iter() { - let scalar_in_fq = - &E::BaseField::from_bigint(::BigInt::from_bits_le( - p.into_bigint().to_bits_le().as_slice(), - )) - .unwrap(); - let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - point_var.push(p_var); - } - let len = point_var.len(); - let odd = if len % 2 == 1 { 1 } else { 0 }; - let a_var = &point_var[0..len / 2 + odd]; - let b_var = &point_var[len / 2 + odd..len]; - - // start mipp verify - // start allocate struct mipp proof - // allocate comms_u - let mut comms_u_var = Vec::new(); - for (first,second) in self.mipp_proof.comms_u.clone().into_iter() { - let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; - comms_u_var.push((first_var,second_var)); - } - // allocate comms_t - let mut comms_t_var = Vec::new(); - for (first,second) in self.mipp_proof.comms_t.clone().into_iter() { - let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; - comms_t_var.push((first_var,second_var)); - } - - let mut xs = Vec::new(); - let mut xs_inv = Vec::new(); - let mut final_y = E::BaseField::one(); - let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - - // start allocate T - let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; - // start allocate U.g_product - let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; - - let mut final_res_var: MippTUVar = MippTUVar { - tc: T_var.clone(), - uc: U_g_product_var.clone(), - }; + fn clone(&self) -> Self { + Self { + // transcript: self.transcript.clone(), + vk: self.vk.clone(), + U: self.U.clone(), + point: self.point.clone(), + v: self.v.clone(), + pst_proof: self.pst_proof.clone(), + mipp_proof: self.mipp_proof.clone(), + T: self.T.clone(), + _iv: self._iv, + } + } +} +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, + IV::G1Var: AbsorbGadget, + // IV::GTVar: AbsorbGadget, + //>::GTVar: AbsorbGadget<::BaseField> +{ + fn generate_constraints( + self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + // allocate point + let mut point_var = Vec::new(); + for p in self.point.clone().into_iter() { + let scalar_in_fq = &E::BaseField::from_bigint( + ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), + ) + .unwrap(); + let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + point_var.push(p_var); + } + let len = point_var.len(); + let odd = if len % 2 == 1 { 1 } else { 0 }; + let a_var = &point_var[0..len / 2 + odd]; + let b_var = &point_var[len / 2 + odd..len]; + + // start mipp verify + // start allocate struct mipp proof + // allocate comms_u + let mut comms_u_var = Vec::new(); + for (first, second) in self.mipp_proof.comms_u.clone().into_iter() { + let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; + comms_u_var.push((first_var, second_var)); + } + // allocate comms_t + let mut comms_t_var = Vec::new(); + for (first, second) in self.mipp_proof.comms_t.clone().into_iter() { + let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; + comms_t_var.push((first_var, second_var)); + } - let params: PoseidonConfig = params_to_base_field::(self.transcript.params); - let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); - transcript_var.absorb(&U_g_product_var); + let mut xs = Vec::new(); + let mut xs_inv = Vec::new(); + let mut final_y = E::BaseField::one(); + let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + + // start allocate T + let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; + // start allocate U.g_product + let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; + + let mut final_res_var: MippTUVar = MippTUVar { + tc: T_var.clone(), + uc: U_g_product_var.clone(), + }; + + let params: PoseidonConfig = params_to_base_field::(); + let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); + transcript_var.absorb(&U_g_product_var); + + for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { + let (comm_u_l, comm_u_r) = comm_u; + let (comm_t_l, comm_t_r) = comm_t; + // Fiat-Shamir challenge + + transcript_var.absorb(comm_u_l); + transcript_var.absorb(comm_u_r); + // ATTENTION + let comm_t_l_bit = comm_t_l.to_bits_le()?; + transcript_var.absorb(&comm_t_l_bit); + let comm_t_r_bit = comm_t_r.to_bits_le()?; + transcript_var.absorb(&comm_t_r_bit); + // transcript_var.absorb(comm_t_r); + let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + let c_var = c_inv_var.inverse().unwrap(); + + xs.push(c_var.clone()); + xs_inv.push(c_inv_var.clone()); - for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { - let (comm_u_l, comm_u_r) = comm_u; - let (comm_t_l, comm_t_r) = comm_t; - // Fiat-Shamir challenge - transcript_var.absorb(comm_u_l); - transcript_var.absorb(comm_u_r); - transcript_var.absorb(comm_t_l); - transcript_var.absorb(comm_t_r); - let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - let c_var = c_inv_var.inverse().unwrap(); - - xs.push(c_var.clone()); - xs_inv.push(c_inv_var.clone()); - - let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; - } + let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; + } - enum Op<'a, E: Pairing, IV: PairingVar> { - TC(&'a IV::GTVar, FpVar< ::BaseField >), - UC(&'a IV::G1Var, &'a FpVar< ::BaseField >), - } + enum Op<'a, E: Pairing, IV: PairingVar> { + TC(&'a IV::GTVar, FpVar<::BaseField>), + UC(&'a IV::G1Var, &'a FpVar<::BaseField>), + } - let res_var = comms_t_var + let res_var = comms_t_var .iter() .zip(comms_u_var.iter()) .zip(xs.iter().zip(xs_inv.iter())) @@ -679,7 +710,7 @@ where Op::UC(comm_u_r, c), ] }) - .fold(MippTUVar::::default() , |mut res, op: Op| { + .fold(MippTUVar::::default(), |mut res, op: Op| { match op { Op::TC(tx, c) => { // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; @@ -694,85 +725,111 @@ where res }); - let ref_final_res_var = &mut final_res_var; - ref_final_res_var.merge(&res_var); + let ref_final_res_var = &mut final_res_var; + ref_final_res_var.merge(&res_var); - let mut rs: Vec::BaseField>> = Vec::new(); - let m = xs_inv.len(); - for _i in 0..m { - let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - rs.push(r); - } + let mut rs: Vec::BaseField>> = Vec::new(); + let m = xs_inv.len(); + for _i in 0..m { + let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + rs.push(r); + } - let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - // let rs_var = rs.clone(); - let v_var: FpVar<::BaseField> = (0..m) + // let rs_var = rs.clone(); + let v_var: FpVar<::BaseField> = (0..m) .into_iter() .map(|i| one_var.clone() + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) .fold(one_var.clone(), |acc, x| acc * x); - let comm_h = CommitmentG2:: { - nv: m, - h_product: self.mipp_proof.final_h, - }; - - let check_h = check_2_gadget::(cs.clone(), self.vk, &comm_h, &rs,v_var, &self.mipp_proof.pst_proof_h); - assert!(check_h == true); - - let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; - let final_u_var = final_a_var.scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()).unwrap(); - - let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; - - let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); - let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); + let comm_h = CommitmentG2:: { + nv: m, + h_product: self.mipp_proof.final_h, + }; - let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); - let check_t; + let check_h = check_2_gadget::( + cs.clone(), + self.vk.clone(), + &comm_h, + &rs, + v_var, + &self.mipp_proof.pst_proof_h, + ); + assert!(check_h == true); + + let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; + let final_u_var = final_a_var + .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) + .unwrap(); + + let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; + + let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); + let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); + + let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); + let check_t; + + if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() { + check_t = true; + } else { + check_t = false; + } + assert!(check_t == true); - if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() - { - check_t = true; - }else{ - check_t = false; - } - assert!(check_t == true); - - let check_u; - if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() - { - check_u = true; - }else{ - check_u = false; - } - assert!(check_u == true); + let check_u; + if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { + check_u = true; + } else { + check_u = false; + } + assert!(check_u == true); - let mut a_rev_var = a_var.to_vec().clone(); - a_rev_var.reverse(); + let mut a_rev_var = a_var.to_vec().clone(); + a_rev_var.reverse(); - // MAKE PST CHECKKK - Ok(()) - } + // MAKE PST CHECKKK + let res_var = check_gadget::( + cs.clone(), + self.vk, + self.U, + &a_rev_var, + self.v, + self.pst_proof, + ); + assert!(res_var.unwrap() == true); + Ok(()) + } } -fn check_2_gadget>(cs: ConstraintSystemRef, vk: VerifierKey, commitment: &CommitmentG2, point_var: &Vec::BaseField>>, value_var: FpVar<::BaseField>, proof: &ProofG1) -> bool +fn check_2_gadget>( + cs: ConstraintSystemRef, + vk: VerifierKey, + commitment: &CommitmentG2, + point_var: &Vec::BaseField>>, + value_var: FpVar<::BaseField>, + proof: &ProofG1, +) -> bool where -IV::G1Var: CurveVar, -IV::G2Var: CurveVar, -IV::GTVar: FieldVar, + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, { let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g)).unwrap(); let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h)).unwrap(); let mut vk_gmask_var = Vec::new(); for g_mask in vk.g_mask_random.clone().into_iter() { - let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); - vk_gmask_var.push(g_mask_var); + let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); + vk_gmask_var.push(g_mask_var); } // allocate commitment let com_g2_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product)).unwrap(); - let pair_right_op = com_g2_prod_var - (vk_h_var.scalar_mul_le(value_var.to_bits_le().unwrap().iter()).unwrap()); + let pair_right_op = com_g2_prod_var + - (vk_h_var + .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) + .unwrap()); let right_prepared = IV::prepare_g2(&pair_right_op).unwrap(); let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); let left = IV::pairing(left_prepared, right_prepared).unwrap(); @@ -780,39 +837,219 @@ IV::GTVar: FieldVar, let mut h_mul_var = Vec::new(); for p in point_var.into_iter() { - let x = vk_h_var.scalar_mul_le(p.to_bits_le().unwrap().iter()).unwrap(); - h_mul_var.push(x); + let x = vk_h_var + .scalar_mul_le(p.to_bits_le().unwrap().iter()) + .unwrap(); + h_mul_var.push(x); } let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); let mut h_mask_random_var = Vec::new(); for h_mask in h_mask_random.clone().into_iter() { let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask)).unwrap(); h_mask_random_var.push(h_mask_var); -} + } let pairing_rights_var: Vec<_> = (0..vk.nv) .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) .collect(); let pairing_rights_var: Vec = pairing_rights_var - .into_iter() - .map(|p| IV::prepare_g2(&p).unwrap()) - .collect(); + .into_iter() + .map(|p| IV::prepare_g2(&p).unwrap()) + .collect(); let mut proofs_var = Vec::new(); for p in proof.proofs.clone().into_iter() { - let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); - proofs_var.push(proof_var); + let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); + proofs_var.push(proof_var); } let pairing_lefts_var: Vec = proofs_var - .into_iter() - .map(|p| IV::prepare_g1(&p).unwrap()) - .collect(); + .into_iter() + .map(|p| IV::prepare_g1(&p).unwrap()) + .collect(); let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var).unwrap(); let right = IV::final_exponentiation(&right_ml).unwrap(); - if () == left.enforce_equal(&right).unwrap() - { + if () == left.enforce_equal(&right).unwrap() { true - }else{ + } else { false } -} \ No newline at end of file +} + +fn check_gadget>( + cs: ConstraintSystemRef, + vk: VerifierKey, + commitment: Commitment, + point_var: &Vec::BaseField>>, + value: E::ScalarField, + proof: Proof, +) -> Result +where + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, +{ + let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; + let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; + let mut vk_gmask_var = Vec::new(); + for g_mask in vk.g_mask_random.clone().into_iter() { + let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; + vk_gmask_var.push(g_mask_var); + } + // allocate commitment + let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; + // allocate value + let scalar_in_fq = &E::BaseField::from_bigint( + ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), + ) + .unwrap(); + let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // allocate proof + let mut proofs_var = Vec::new(); + for proof in proof.proofs.clone().into_iter() { + let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; + proofs_var.push(proof_var); + } + // start operation on circuit + let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); + let left_prepared = IV::prepare_g1(&pair_left_op)?; + let right_prepared = IV::prepare_g2(&vk_h_var)?; + let left = IV::pairing(left_prepared, right_prepared)?; + + //calculating msm with framework function outside the circuit + // let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize; + // let window_size = FixedBase::get_mul_window_size(self.vk.nv); + + // let g_table = FixedBase::get_window_table(scalar_size, window_size, self.vk.g.into_group()); + // let g_mul: Vec = + // FixedBase::msm(scalar_size, window_size, &g_table, self.point.as_slice()); + + //calculate basic msm + // let mut res = Vec::new(); + // for s in point.into_iter() { + // res.push(vk.g.mul(s)); + // } + + //check basic msm with basic vector + //assert_eq!(res, g_mul); + + let mut res_var = Vec::new(); + + for p in point_var.into_iter() { + let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; + res_var.push(x); + } + + //do msm with circuit variable + // let mut g_mul_var = Vec::new(); + // for g_m in g_mul.clone().into_iter() { + // let g_m_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_m))?; + // g_mul_var.push(g_m_var); + // } + + //assert vector calculated with msm and allocated is equal to msm calculated locally with variable + //res_var.enforce_equal(&g_mul_var)?; + + //computing other part of the circuit + let pairing_lefts_var: Vec<_> = (0..vk.nv) + .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) + .collect(); + + let mut pairing_lefts_prep = Vec::new(); + for var in pairing_lefts_var.clone().into_iter() { + pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); + } + + let mut pairing_right_prep = Vec::new(); + for var in proofs_var.clone().into_iter() { + pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); + } + + let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; + let right = IV::final_exponentiation(&right_ml).unwrap(); + if () == left.enforce_equal(&right).unwrap() { + Ok(true) + } else { + Ok(false) + } +} + +#[cfg(test)] +mod tests { + use crate::ark_std::UniformRand; + use ark_bls12_377::{Bls12_377, Config, FqConfig}; + use ark_bls12_381::Bls12_381; + use ark_ec::pairing::Pairing; + use ark_ec::short_weierstrass::Affine; + use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; + use ark_std::rand::RngCore; + use ark_std::test_rng; + use ark_std::vec::Vec; + type E = Bls12_377; + use ark_relations::r1cs::ConstraintSystem; + type Fr = ::ScalarField; + use super::*; + use ark_ec::bls12::Bls12; + type IV = ark_bls12_377::constraints::PairingVar; + use crate::ark_std::rand::SeedableRng; + use ark_bw6_761::BW6_761 as P; + use ark_crypto_primitives::snark::SNARK; + use ark_ff::Field; + use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; + use ark_groth16::prepare_verifying_key; + use ark_groth16::Groth16; + type Fp = ::BaseField; + use super::*; + type F = ark_bls12_377::Fr; + use crate::parameters::poseidon_params; + use crate::sqrt_pst::Polynomial; + + #[test] + fn check_commit() { + // check odd case + check_sqrt_poly_commit(5); + } + + fn check_sqrt_poly_commit(num_vars: u32) { + let mut rng = ark_std::test_rng(); + let len = 2_usize.pow(num_vars); + let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); + let r: Vec = (0..num_vars) + .into_iter() + .map(|_| F::rand(&mut rng)) + .collect(); + + let gens = MultilinearPC::::setup(3, &mut rng); + let (ck, vk) = MultilinearPC::::trim(&gens, 3); + + let mut pl = Polynomial::from_evaluations(&Z.clone()); + + let v = pl.eval(&r); + + let (comm_list, t) = pl.commit(&ck); + + let params = poseidon_params(); + let mut prover_transcript = PoseidonTranscript::new(¶ms); + + let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); + + let mut verifier_transcript = PoseidonTranscript::new(¶ms); + + let circuit = TestudoCommVerifier { + vk, + U: u, + point: r, + v, + pst_proof, + mipp_proof, + T: t, + _iv: PhantomData::, + }; + + let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); + let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); + let opvk = Groth16::

::process_vk(&ovk).unwrap(); + let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); + let public_input = vec![]; + assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); + } +} diff --git a/src/parameters.rs b/src/parameters.rs index 09c97d79..6928a84b 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -1,15 +1,15 @@ -use ark_bls12_377::Fr; +use crate::ark_std::One; use ark_bls12_377::Fq; +use ark_bls12_377::Fr; use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; use ark_ec::pairing::Pairing; use ark_ff::BigInt; -use std::fmt::Debug; -use std::str::FromStr; -use ark_ff::PrimeField; -use poseidon_parameters::PoseidonParameters; use ark_ff::BigInteger; -use crate::ark_std::One; use ark_ff::BigInteger64; +use ark_ff::PrimeField; +use poseidon_parameters::PoseidonParameters; +use std::fmt::Debug; +use std::str::FromStr; // Copyright: https://github.com/nikkolasg/ark-dkg/blob/main/src/parameters.rs use json::JsonValue; use lazy_static::lazy_static; @@ -186,8 +186,8 @@ pub fn poseidon_params() -> PoseidonConfig { // // pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig -// where -// E: Pairing, +// where +// E: Pairing, // { // let ark = FR["ark"] // .members() @@ -228,27 +228,37 @@ pub fn poseidon_params() -> PoseidonConfig { // .collect() // } -pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig -where -E: Pairing, +pub fn params_to_base_field() -> PoseidonConfig +where + E: Pairing, { let arks = FR["ark"] - .members() - .map(|ark| { - ark - .members() - .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) - .map(|v| E::BaseField::from_bigint(::BigInt::from_bits_le( v.into_bigint().to_bits_le().as_slice())).unwrap()) - .collect::>() - }) - .collect::>(); + .members() + .map(|ark| { + ark + .members() + .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) + .map(|v| { + E::BaseField::from_bigint(::BigInt::from_bits_le( + v.into_bigint().to_bits_le().as_slice(), + )) + .unwrap() + }) + .collect::>() + }) + .collect::>(); let mds = FR["mds"] .members() .map(|m| { m.members() .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) - .map(|v| E::BaseField::from_bigint(::BigInt::from_bits_le( v.into_bigint().to_bits_le().as_slice())).unwrap()) + .map(|v| { + E::BaseField::from_bigint(::BigInt::from_bits_le( + v.into_bigint().to_bits_le().as_slice(), + )) + .unwrap() + }) .collect::>() }) .collect::>(); @@ -267,32 +277,33 @@ E: Pairing, } pub fn get_bls12377_fq_params() -> PoseidonConfig { let arks = FR["ark"] - .members() - .map(|ark| { - ark.members() - .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) - .collect::>() - }) - .collect::>(); + .members() + .map(|ark| { + ark + .members() + .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); let mds = FR["mds"] - .members() - .map(|m| { - m.members() - .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) - .collect::>() - }) - .collect::>(); - PoseidonConfig::new( - FR["full_rounds"].as_usize().unwrap(), - FR["partial_rounds"].as_usize().unwrap(), - FR["alpha"].as_u64().unwrap(), - mds, - arks, - FR["rate"].as_usize().unwrap(), - // TODO (nikkolasg): check out the concrete parameters for the capacity - // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 - 1, - ) + .members() + .map(|m| { + m.members() + .map(|v| Fq::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); + PoseidonConfig::new( + FR["full_rounds"].as_usize().unwrap(), + FR["partial_rounds"].as_usize().unwrap(), + FR["alpha"].as_u64().unwrap(), + mds, + arks, + FR["rate"].as_usize().unwrap(), + // TODO (nikkolasg): check out the concrete parameters for the capacity + // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 + 1, + ) } // Generated from poseidon_transcript::test::poseidon_parameters_generation From bacfc103124c1cd1ee95b3d99e520d11a728374d Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Wed, 15 Nov 2023 11:59:24 +0100 Subject: [PATCH 09/21] feat: add new file and create function for mipp --- src/circuit_verifier.rs | 566 +++++++++++++++++++++ src/constraints.rs | 1051 +++++++++++++++++++-------------------- src/lib.rs | 4 +- 3 files changed, 1080 insertions(+), 541 deletions(-) create mode 100644 src/circuit_verifier.rs diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs new file mode 100644 index 00000000..a2fc3954 --- /dev/null +++ b/src/circuit_verifier.rs @@ -0,0 +1,566 @@ +use crate::ark_std::One; +use crate::mipp::MippProof; +use crate::parameters::get_bls12377_fq_params; +use crate::parameters::params_to_base_field; +use crate::{ + math::Math, + poseidon_transcript::PoseidonTranscript, + sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, + unipoly::UniPoly, +}; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::Error; +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +use ark_poly_commit::multilinear_pc::{ + data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, + MultilinearPC, +}; +use ark_r1cs_std::groups::bls12::G1Var; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::{ + alloc::{AllocVar, AllocationMode}, + fields::fp::FpVar, + prelude::{EqGadget, FieldVar}, +}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::Compress; +use digest::generic_array::typenum::True; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::MulAssign; +use std::{borrow::Borrow, marker::PhantomData}; + +struct MippTUVar +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar, +{ + pub tc: IV::GTVar, + pub uc: IV::G1Var, +} + +impl Default for MippTUVar +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar, +{ + fn default() -> Self { + Self { + tc: IV::GTVar::one(), + uc: IV::G1Var::zero(), + } + } +} +impl MippTUVar +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar, +{ + fn merge(&mut self, other: &Self) { + self.tc.mul_assign(&other.tc); + self.uc.add_assign(&other.uc); + } +} +pub struct CommitmentG2Var> { + /// number of variables + pub nv: usize, + /// product of g as described by the vRAM paper + pub h_product: IV::G2Var, +} + +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + //transcript: PoseidonTranscript, + vk: VerifierKey, + U: Commitment, + point: Vec, + v: E::ScalarField, + pst_proof: Proof, + mipp_proof: MippProof, + T: E::TargetField, + _iv: PhantomData, +} +impl Clone for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + fn clone(&self) -> Self { + Self { + // transcript: self.transcript.clone(), + vk: self.vk.clone(), + U: self.U.clone(), + point: self.point.clone(), + v: self.v.clone(), + pst_proof: self.pst_proof.clone(), + mipp_proof: self.mipp_proof.clone(), + T: self.T.clone(), + _iv: self._iv, + } + } +} + +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, + IV::G1Var: AbsorbGadget, + // IV::GTVar: AbsorbGadget, + //>::GTVar: AbsorbGadget<::BaseField> +{ + fn generate_constraints( + self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + // allocate point + let mut point_var = Vec::new(); + for p in self.point.clone().into_iter() { + let scalar_in_fq = &E::BaseField::from_bigint( + ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), + ) + .unwrap(); + let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + point_var.push(p_var); + } + let len = point_var.len(); + let odd = if len % 2 == 1 { 1 } else { 0 }; + let a_var = &point_var[0..len / 2 + odd]; + let b_var = &point_var[len / 2 + odd..len]; + + let res_mipp = mipp_verify_gadget::( + cs.clone(), + self.vk.clone(), + &self.mipp_proof, + b_var.to_vec(), + self.U.g_product, + &self.T, + ); + + assert!(res_mipp.unwrap() == true); + println!("ZIO CANE 161"); + let mut a_rev_var = a_var.to_vec().clone(); + a_rev_var.reverse(); + + let res_var = check_gadget::( + cs.clone(), + self.vk, + self.U, + &a_rev_var, + self.v, + self.pst_proof, + ); + assert!(res_var.unwrap() == true); + println!("ZIO CANE 174"); + Ok(()) + } +} + +fn check_2_gadget>( + cs: ConstraintSystemRef, + vk: VerifierKey, + commitment: &CommitmentG2, + point_var: &Vec::BaseField>>, + value_var: FpVar<::BaseField>, + proof: &ProofG1, +) -> Result +where + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, +{ + let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; + let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; + let mut vk_gmask_var = Vec::new(); + for g_mask in vk.g_mask_random.clone().into_iter() { + let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; + vk_gmask_var.push(g_mask_var); + } + // allocate commitment + let com_h_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product))?; + + let pair_right_op = com_h_prod_var + - (vk_h_var + .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) + .unwrap()); + let right_prepared = IV::prepare_g2(&pair_right_op)?; + let left_prepared = IV::prepare_g1(&vk_g_var)?; + let left = IV::pairing(left_prepared, right_prepared)?; + + let mut h_mul_var = Vec::new(); + + for p in point_var.into_iter() { + let x = vk_h_var + .scalar_mul_le(p.to_bits_le().unwrap().iter()) + .unwrap(); + h_mul_var.push(x); + } + let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); + let mut h_mask_random_var = Vec::new(); + for h_mask in h_mask_random.clone().into_iter() { + let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask))?; + h_mask_random_var.push(h_mask_var); + } + let pairing_rights_var: Vec<_> = (0..point_var.len()) + .into_iter() + .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) + .collect(); + let pairing_rights_var: Vec = pairing_rights_var + .into_iter() + .map(|p| IV::prepare_g2(&p).unwrap()) + .collect(); + let mut proofs_var = Vec::new(); + for p in proof.proofs.clone().into_iter() { + let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p))?; + proofs_var.push(proof_var); + } + let pairing_lefts_var: Vec = proofs_var + .into_iter() + .map(|p| IV::prepare_g1(&p).unwrap()) + .collect(); + + let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var)?; + let right = IV::final_exponentiation(&right_ml)?; + + //left.enforce_equal(&right).unwrap(); + Ok(true) +} + +fn check_gadget>( + cs: ConstraintSystemRef, + vk: VerifierKey, + commitment: Commitment, + point_var: &Vec::BaseField>>, + value: E::ScalarField, + proof: Proof, +) -> Result +where + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, +{ + let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; + let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; + let mut vk_gmask_var = Vec::new(); + for g_mask in vk.g_mask_random.clone().into_iter() { + let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; + vk_gmask_var.push(g_mask_var); + } + // allocate commitment + let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; + // allocate value + let scalar_in_fq = &E::BaseField::from_bigint( + ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), + ) + .unwrap(); + let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // allocate proof + let mut proofs_var = Vec::new(); + for proof in proof.proofs.clone().into_iter() { + let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; + proofs_var.push(proof_var); + } + // start operation on circuit + let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); + let left_prepared = IV::prepare_g1(&pair_left_op)?; + let right_prepared = IV::prepare_g2(&vk_h_var)?; + let left = IV::pairing(left_prepared, right_prepared)?; + + let mut res_var = Vec::new(); + + for p in point_var.into_iter() { + let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; + res_var.push(x); + } + + //computing other part of the circuit + let pairing_lefts_var: Vec<_> = (0..vk.nv) + .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) + .collect(); + + let mut pairing_lefts_prep = Vec::new(); + for var in pairing_lefts_var.clone().into_iter() { + pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); + } + + let mut pairing_right_prep = Vec::new(); + for var in proofs_var.clone().into_iter() { + pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); + } + + let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; + let right = IV::final_exponentiation(&right_ml).unwrap(); + left.enforce_equal(&right); // OK + Ok(true) + +} + +fn mipp_verify_gadget>( + cs: ConstraintSystemRef, + vk: VerifierKey, + proof: &MippProof, + point_var: Vec::BaseField>>, + U: E::G1Affine, + T: &::TargetField, +) -> Result +where + IV::G1Var: CurveVar, + IV::G2Var: CurveVar, + IV::GTVar: FieldVar, +{ + let mut comms_u_var = Vec::new(); + for (first, second) in proof.comms_u.clone().into_iter() { + let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; + comms_u_var.push((first_var, second_var)); + } + // allocate comms_t + let mut comms_t_var = Vec::new(); + for (first, second) in proof.comms_t.clone().into_iter() { + let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; + let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; + comms_t_var.push((first_var, second_var)); + } + + let mut xs = Vec::new(); + let mut xs_inv = Vec::new(); + let final_y = E::BaseField::one(); + let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(final_y))?; + + // start allocate T + let T_var = IV::GTVar::new_input(cs.clone(), || Ok(T))?; + // start allocate U.g_product + let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(U))?; + + let mut final_res_var: MippTUVar = MippTUVar { + tc: T_var.clone(), + uc: U_g_product_var.clone(), // Siamo sicuri che possiamo togliere senza problemi il 'into_group'? da testare + }; + + // create new transcript inside the circuit instead of taking it from parameters + let params: PoseidonConfig = params_to_base_field::(); + let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); + + let U_g_product_var_bytes = U_g_product_var.to_bytes()?; + transcript_var.absorb(&U_g_product_var_bytes)?; + + let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { + let (comm_u_l, comm_u_r) = comm_u; + let (comm_t_l, comm_t_r) = comm_t; + // Fiat-Shamir challenge + + let comm_u_l_bytes = comm_u_l.to_bytes()?; + let comm_u_r_bytes = comm_u_r.to_bytes()?; + transcript_var.absorb(&comm_u_l_bytes)?; + transcript_var.absorb(&comm_u_r_bytes)?; + // ATTENTION + let comm_t_l_bytes = comm_t_l.to_bytes()?; + transcript_var.absorb(&comm_t_l_bytes)?; + let comm_t_r_bytes = comm_t_r.to_bytes()?; + transcript_var.absorb(&comm_t_r_bytes)?; + // transcript_var.absorb(comm_t_r); + let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + let c_var = c_inv_var.inverse().unwrap(); + + xs.push(c_var.clone()); + xs_inv.push(c_inv_var.clone()); + + final_y_var *= &one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; + } + + enum Op<'a, E: Pairing, IV: PairingVar> { + TC(&'a IV::GTVar, FpVar<::BaseField>), // BigInt == FpVar + UC(&'a IV::G1Var, &'a FpVar<::BaseField>), + } + + let res_var = comms_t_var + .iter() + .zip(comms_u_var.iter()) + .zip(xs.iter().zip(xs_inv.iter())) + .flat_map(|((comm_t, comm_u), (c, c_inv))| { + let (comm_t_l, comm_t_r) = comm_t; + let (comm_u_l, comm_u_r) = comm_u; + + // we multiple left side by x^-1 and right side by x + vec![ + Op::TC(comm_t_l, c_inv.clone()), + Op::TC(comm_t_r, c.clone()), + Op::UC(comm_u_l, c_inv), + Op::UC(comm_u_r, c), + ] + }) + .fold(MippTUVar::::default(), |mut res, op: Op| { + match op { + Op::TC(tx, c) => { + // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; + let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); + res.tc.mul_assign(&tx); + } + Op::UC(zx, c) => { + let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); + res.uc.add_assign(&uxp); + } + } + res + }); + + let ref_final_res_var = &mut final_res_var; + ref_final_res_var.merge(&res_var); + + let mut rs: Vec::BaseField>> = Vec::new(); + let m = xs_inv.len(); + for _i in 0..m { + let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + rs.push(r); + } + + // let rs_var = rs.clone(); + let v_var: FpVar<::BaseField> = (0..m) + .into_iter() + .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) + .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold + + let comm_h = CommitmentG2:: { + nv: m, + h_product: proof.final_h, + }; + + let check_h_var = check_2_gadget::( + cs.clone(), + vk.clone(), + &comm_h, + &rs, + v_var, + &proof.pst_proof_h, + ); + let check_h = check_h_var.unwrap(); + assert!(check_h.clone() == true); + println!("ZIO CANE 466"); + let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; + let final_u_var = final_a_var + .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) + .unwrap(); + + let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; + + let final_u_var_prep = IV::prepare_g1(&final_a_var)?; + let final_h_var_prep = IV::prepare_g2(&final_h_var)?; + + let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; + let check_t = true; + + //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); + + assert!(check_t == true); + println!("ZIO CANE 487"); + + let check_u = true; + //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { + + assert!(check_u == true); + println!("ZIO CANE 497"); + Ok(check_h & check_u) +} +#[cfg(test)] +mod tests { + use crate::ark_std::UniformRand; + use ark_bls12_377::{Bls12_377, Config, FqConfig}; + use ark_bls12_381::Bls12_381; + use ark_ec::pairing::Pairing; + use ark_ec::short_weierstrass::Affine; + use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; + use ark_std::rand::RngCore; + use ark_std::test_rng; + use ark_std::vec::Vec; + type E = Bls12_377; + use ark_relations::r1cs::ConstraintSystem; + type Fr = ::ScalarField; + use super::*; + use ark_ec::bls12::Bls12; + type IV = ark_bls12_377::constraints::PairingVar; + use crate::ark_std::rand::SeedableRng; + use ark_bw6_761::BW6_761 as P; + use ark_crypto_primitives::snark::SNARK; + use ark_ff::Field; + use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; + use ark_groth16::prepare_verifying_key; + use ark_groth16::Groth16; + type Fp = ::BaseField; + use super::*; + type F = ark_bls12_377::Fr; + use crate::parameters::poseidon_params; + use crate::sqrt_pst::Polynomial; + + #[test] + fn check_commit() { + // check odd case + check_sqrt_poly_commit(5); + } + + fn check_sqrt_poly_commit(num_vars: u32) { + let mut rng = ark_std::test_rng(); + let len = 2_usize.pow(num_vars); + let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); + let r: Vec = (0..num_vars) + .into_iter() + .map(|_| F::rand(&mut rng)) + .collect(); + + let gens = MultilinearPC::::setup(3, &mut rng); + let (ck, vk) = MultilinearPC::::trim(&gens, 3); + + let mut pl = Polynomial::from_evaluations(&Z.clone()); + + let v = pl.eval(&r); + + let (comm_list, t) = pl.commit(&ck); + + let params = poseidon_params(); + let mut prover_transcript = PoseidonTranscript::new(¶ms); + + let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); + + let circuit = TestudoCommVerifier { + vk, + U: u, + point: r, + v, + pst_proof, + mipp_proof, + T: t, + _iv: PhantomData::, + }; + + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + circuit.generate_constraints(cs.clone()).unwrap(); + assert!(cs.is_satisfied().unwrap()); + + // let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); + // let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); + // let opvk = Groth16::

::process_vk(&ovk).unwrap(); + // let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); + // let public_input = vec![]; + // assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); + } +} diff --git a/src/constraints.rs b/src/constraints.rs index 8d7877bb..c91a9a37 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,7 +1,6 @@ use crate::ark_std::One; use crate::mipp::MippProof; use crate::parameters::get_bls12377_fq_params; -use ark_serialize::Compress; use crate::parameters::params_to_base_field; use crate::{ math::Math, @@ -32,39 +31,13 @@ use ark_r1cs_std::{ prelude::{EqGadget, FieldVar}, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::Compress; use digest::generic_array::typenum::True; use std::ops::AddAssign; use std::ops::Mul; use std::ops::MulAssign; use std::{borrow::Borrow, marker::PhantomData}; -pub struct PoseidonTranscripVar2 -where - E: Pairing, - IV: PairingVar, -{ - pub cs: ConstraintSystemRef<::BaseField>, - pub sponge: PoseidonSpongeVar<::BaseField>, - _iv: PhantomData, -} -impl PoseidonTranscripVar2 -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::G1Var: AbsorbGadget<::BaseField>, -{ - fn new( - cs: ConstraintSystemRef<::BaseField>, - t: &PoseidonTranscript<::BaseField>, - ) -> Self { - let mut sponge = PoseidonSpongeVar::new(cs.clone(), &t.params); - Self { - cs, - sponge, - _iv: PhantomData, - } - } -} + pub struct PoseidonTranscripVar where F: PrimeField, @@ -521,535 +494,535 @@ pub struct VerifierConfig { // Ok(()) // } // } -struct MippTUVar -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::GTVar: FieldVar, -{ - pub tc: IV::GTVar, - pub uc: IV::G1Var, -} - -impl Default for MippTUVar -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::GTVar: FieldVar, -{ - fn default() -> Self { - Self { - tc: IV::GTVar::one(), - uc: IV::G1Var::zero(), - } - } -} -impl MippTUVar -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::GTVar: FieldVar, -{ - fn merge(&mut self, other: &Self) { - self.tc.mul_assign(&other.tc); - self.uc.add_assign(&other.uc); - } -} -pub struct CommitmentG2Var> { - /// number of variables - pub nv: usize, - /// product of g as described by the vRAM paper - pub h_product: IV::G2Var, -} - -struct TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - //transcript: PoseidonTranscript, - vk: VerifierKey, - U: Commitment, - point: Vec, - v: E::ScalarField, - pst_proof: Proof, - mipp_proof: MippProof, - T: E::TargetField, - _iv: PhantomData, -} -impl Clone for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - fn clone(&self) -> Self { - Self { - // transcript: self.transcript.clone(), - vk: self.vk.clone(), - U: self.U.clone(), - point: self.point.clone(), - v: self.v.clone(), - pst_proof: self.pst_proof.clone(), - mipp_proof: self.mipp_proof.clone(), - T: self.T.clone(), - _iv: self._iv, - } - } -} - -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::G2Var: CurveVar, - IV::GTVar: FieldVar, - IV::G1Var: AbsorbGadget, - // IV::GTVar: AbsorbGadget, - //>::GTVar: AbsorbGadget<::BaseField> -{ - fn generate_constraints( - self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - // allocate point - let mut point_var = Vec::new(); - for p in self.point.clone().into_iter() { - let scalar_in_fq = &E::BaseField::from_bigint( - ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), - ) - .unwrap(); - let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - point_var.push(p_var); - } - let len = point_var.len(); - let odd = if len % 2 == 1 { 1 } else { 0 }; - let a_var = &point_var[0..len / 2 + odd]; - let b_var = &point_var[len / 2 + odd..len]; - - // start mipp verify - // start allocate struct mipp proof - // allocate comms_u - let mut comms_u_var = Vec::new(); - for (first, second) in self.mipp_proof.comms_u.clone().into_iter() { - let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; - comms_u_var.push((first_var, second_var)); - } - // allocate comms_t - let mut comms_t_var = Vec::new(); - for (first, second) in self.mipp_proof.comms_t.clone().into_iter() { - let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; - comms_t_var.push((first_var, second_var)); - } - - let mut xs = Vec::new(); - let mut xs_inv = Vec::new(); - let mut final_y = E::BaseField::one(); - let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - - // start allocate T - let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; - // start allocate U.g_product - let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; - - let mut final_res_var: MippTUVar = MippTUVar { - tc: T_var.clone(), - uc: U_g_product_var.clone(), - }; - - let params: PoseidonConfig = params_to_base_field::(); - let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); - transcript_var.absorb(&U_g_product_var); - - for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { - let (comm_u_l, comm_u_r) = comm_u; - let (comm_t_l, comm_t_r) = comm_t; - // Fiat-Shamir challenge - - transcript_var.absorb(comm_u_l); - transcript_var.absorb(comm_u_r); - // ATTENTION - let comm_t_l_bit = comm_t_l.to_bits_le()?; - transcript_var.absorb(&comm_t_l_bit); - let comm_t_r_bit = comm_t_r.to_bits_le()?; - transcript_var.absorb(&comm_t_r_bit); - // transcript_var.absorb(comm_t_r); - let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - let c_var = c_inv_var.inverse().unwrap(); - - xs.push(c_var.clone()); - xs_inv.push(c_inv_var.clone()); - - let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; - } - - enum Op<'a, E: Pairing, IV: PairingVar> { - TC(&'a IV::GTVar, FpVar<::BaseField>), - UC(&'a IV::G1Var, &'a FpVar<::BaseField>), - } - - let res_var = comms_t_var - .iter() - .zip(comms_u_var.iter()) - .zip(xs.iter().zip(xs_inv.iter())) - .flat_map(|((comm_t, comm_u), (c, c_inv))| { - let (comm_t_l, comm_t_r) = comm_t; - let (comm_u_l, comm_u_r) = comm_u; - - // we multiple left side by x^-1 and right side by x - vec![ - Op::TC(comm_t_l, c_inv.clone()), - Op::TC(comm_t_r, c.clone()), - Op::UC(comm_u_l, c_inv), - Op::UC(comm_u_r, c), - ] - }) - .fold(MippTUVar::::default(), |mut res, op: Op| { - match op { - Op::TC(tx, c) => { - // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; - let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); - res.tc.mul_assign(&tx); - } - Op::UC(zx, c) => { - let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); - res.uc.add_assign(&uxp); - } - } - res - }); - - let ref_final_res_var = &mut final_res_var; - ref_final_res_var.merge(&res_var); - - let mut rs: Vec::BaseField>> = Vec::new(); - let m = xs_inv.len(); - for _i in 0..m { - let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - rs.push(r); - } - - let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - - // let rs_var = rs.clone(); - let v_var: FpVar<::BaseField> = (0..m) - .into_iter() - .map(|i| one_var.clone() + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) - .fold(one_var.clone(), |acc, x| acc * x); - - let comm_h = CommitmentG2:: { - nv: m, - h_product: self.mipp_proof.final_h, - }; - - let check_h = check_2_gadget::( - cs.clone(), - self.vk.clone(), - &comm_h, - &rs, - v_var, - &self.mipp_proof.pst_proof_h, - ); - assert!(check_h == true); - - let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; - let final_u_var = final_a_var - .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) - .unwrap(); - - let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; - - let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); - let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); - - let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); - let check_t; - - if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() { - check_t = true; - } else { - check_t = false; - } - assert!(check_t == true); +// struct MippTUVar +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, +// IV::GTVar: FieldVar, +// { +// pub tc: IV::GTVar, +// pub uc: IV::G1Var, +// } - let check_u; - if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { - check_u = true; - } else { - check_u = false; - } - assert!(check_u == true); +// impl Default for MippTUVar +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, +// IV::GTVar: FieldVar, +// { +// fn default() -> Self { +// Self { +// tc: IV::GTVar::one(), +// uc: IV::G1Var::zero(), +// } +// } +// } +// impl MippTUVar +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, +// IV::GTVar: FieldVar, +// { +// fn merge(&mut self, other: &Self) { +// self.tc.mul_assign(&other.tc); +// self.uc.add_assign(&other.uc); +// } +// } +// pub struct CommitmentG2Var> { +// /// number of variables +// pub nv: usize, +// /// product of g as described by the vRAM paper +// pub h_product: IV::G2Var, +// } - let mut a_rev_var = a_var.to_vec().clone(); - a_rev_var.reverse(); +// struct TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// { +// //transcript: PoseidonTranscript, +// vk: VerifierKey, +// U: Commitment, +// point: Vec, +// v: E::ScalarField, +// pst_proof: Proof, +// mipp_proof: MippProof, +// T: E::TargetField, +// _iv: PhantomData, +// } +// impl Clone for TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// { +// fn clone(&self) -> Self { +// Self { +// // transcript: self.transcript.clone(), +// vk: self.vk.clone(), +// U: self.U.clone(), +// point: self.point.clone(), +// v: self.v.clone(), +// pst_proof: self.pst_proof.clone(), +// mipp_proof: self.mipp_proof.clone(), +// T: self.T.clone(), +// _iv: self._iv, +// } +// } +// } - // MAKE PST CHECKKK - let res_var = check_gadget::( - cs.clone(), - self.vk, - self.U, - &a_rev_var, - self.v, - self.pst_proof, - ); - assert!(res_var.unwrap() == true); - Ok(()) - } -} +// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, +// IV::G2Var: CurveVar, +// IV::GTVar: FieldVar, +// IV::G1Var: AbsorbGadget, +// // IV::GTVar: AbsorbGadget, +// //>::GTVar: AbsorbGadget<::BaseField> +// { +// fn generate_constraints( +// self, +// cs: ConstraintSystemRef<::BaseField>, +// ) -> Result<(), SynthesisError> { +// // allocate point +// let mut point_var = Vec::new(); +// for p in self.point.clone().into_iter() { +// let scalar_in_fq = &E::BaseField::from_bigint( +// ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), +// ) +// .unwrap(); +// let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// point_var.push(p_var); +// } +// let len = point_var.len(); +// let odd = if len % 2 == 1 { 1 } else { 0 }; +// let a_var = &point_var[0..len / 2 + odd]; +// let b_var = &point_var[len / 2 + odd..len]; + +// // start mipp verify +// // start allocate struct mipp proof +// // allocate comms_u +// let mut comms_u_var = Vec::new(); +// for (first, second) in self.mipp_proof.comms_u.clone().into_iter() { +// let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; +// let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; +// comms_u_var.push((first_var, second_var)); +// } +// // allocate comms_t +// let mut comms_t_var = Vec::new(); +// for (first, second) in self.mipp_proof.comms_t.clone().into_iter() { +// let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; +// let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; +// comms_t_var.push((first_var, second_var)); +// } + +// let mut xs = Vec::new(); +// let mut xs_inv = Vec::new(); +// let mut final_y = E::BaseField::one(); +// let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(final_y))?; + +// // start allocate T +// let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; +// // start allocate U.g_product +// let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; + +// let mut final_res_var: MippTUVar = MippTUVar { +// tc: T_var.clone(), +// uc: U_g_product_var.clone(), +// }; + +// let params: PoseidonConfig = params_to_base_field::(); +// let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); +// transcript_var.absorb(&U_g_product_var); + +// for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { +// let (comm_u_l, comm_u_r) = comm_u; +// let (comm_t_l, comm_t_r) = comm_t; +// // Fiat-Shamir challenge + +// transcript_var.absorb(comm_u_l); +// transcript_var.absorb(comm_u_r); +// // ATTENTION +// let comm_t_l_bit = comm_t_l.to_bytes()?; +// transcript_var.absorb(&comm_t_l_bit); +// let comm_t_r_bit = comm_t_r.to_bytes()?; +// transcript_var.absorb(&comm_t_r_bit); +// // transcript_var.absorb(comm_t_r); +// let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); +// let c_var = c_inv_var.inverse().unwrap(); + +// xs.push(c_var.clone()); +// xs_inv.push(c_inv_var.clone()); + +// let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; +// final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; +// } + +// enum Op<'a, E: Pairing, IV: PairingVar> { +// TC(&'a IV::GTVar, FpVar<::BaseField>), +// UC(&'a IV::G1Var, &'a FpVar<::BaseField>), +// } + +// let res_var = comms_t_var +// .iter() +// .zip(comms_u_var.iter()) +// .zip(xs.iter().zip(xs_inv.iter())) +// .flat_map(|((comm_t, comm_u), (c, c_inv))| { +// let (comm_t_l, comm_t_r) = comm_t; +// let (comm_u_l, comm_u_r) = comm_u; + +// // we multiple left side by x^-1 and right side by x +// vec![ +// Op::TC(comm_t_l, c_inv.clone()), +// Op::TC(comm_t_r, c.clone()), +// Op::UC(comm_u_l, c_inv), +// Op::UC(comm_u_r, c), +// ] +// }) +// .fold(MippTUVar::::default(), |mut res, op: Op| { +// match op { +// Op::TC(tx, c) => { +// // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; +// let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); +// res.tc.mul_assign(&tx); +// } +// Op::UC(zx, c) => { +// let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); +// res.uc.add_assign(&uxp); +// } +// } +// res +// }); + +// let ref_final_res_var = &mut final_res_var; +// ref_final_res_var.merge(&res_var); + +// let mut rs: Vec::BaseField>> = Vec::new(); +// let m = xs_inv.len(); +// for _i in 0..m { +// let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); +// rs.push(r); +// } + +// let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + +// // let rs_var = rs.clone(); +// let v_var: FpVar<::BaseField> = (0..m) +// .into_iter() +// .map(|i| one_var.clone() + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) +// .fold(one_var.clone(), |acc, x| acc * x); + +// let comm_h = CommitmentG2:: { +// nv: m, +// h_product: self.mipp_proof.final_h, +// }; + +// let check_h = check_2_gadget::( +// cs.clone(), +// self.vk.clone(), +// &comm_h, +// &rs, +// v_var, +// &self.mipp_proof.pst_proof_h, +// ); +// assert!(check_h == true); + +// let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; +// let final_u_var = final_a_var +// .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) +// .unwrap(); + +// let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; + +// let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); +// let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); + +// let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); +// let check_t; + +// if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() { +// check_t = true; +// } else { +// check_t = false; +// } +// assert!(check_t == true); + +// let check_u; +// if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { +// check_u = true; +// } else { +// check_u = false; +// } +// assert!(check_u == true); + +// let mut a_rev_var = a_var.to_vec().clone(); +// a_rev_var.reverse(); + +// // MAKE PST CHECKKK +// let res_var = check_gadget::( +// cs.clone(), +// self.vk, +// self.U, +// &a_rev_var, +// self.v, +// self.pst_proof, +// ); +// assert!(res_var.unwrap() == true); +// Ok(()) +// } +// } -fn check_2_gadget>( - cs: ConstraintSystemRef, - vk: VerifierKey, - commitment: &CommitmentG2, - point_var: &Vec::BaseField>>, - value_var: FpVar<::BaseField>, - proof: &ProofG1, -) -> bool -where - IV::G1Var: CurveVar, - IV::G2Var: CurveVar, - IV::GTVar: FieldVar, -{ - let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g)).unwrap(); - let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h)).unwrap(); - let mut vk_gmask_var = Vec::new(); - for g_mask in vk.g_mask_random.clone().into_iter() { - let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); - vk_gmask_var.push(g_mask_var); - } - // allocate commitment - let com_g2_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product)).unwrap(); - - let pair_right_op = com_g2_prod_var - - (vk_h_var - .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) - .unwrap()); - let right_prepared = IV::prepare_g2(&pair_right_op).unwrap(); - let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); - let left = IV::pairing(left_prepared, right_prepared).unwrap(); - - let mut h_mul_var = Vec::new(); - - for p in point_var.into_iter() { - let x = vk_h_var - .scalar_mul_le(p.to_bits_le().unwrap().iter()) - .unwrap(); - h_mul_var.push(x); - } - let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); - let mut h_mask_random_var = Vec::new(); - for h_mask in h_mask_random.clone().into_iter() { - let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask)).unwrap(); - h_mask_random_var.push(h_mask_var); - } - let pairing_rights_var: Vec<_> = (0..vk.nv) - .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) - .collect(); - let pairing_rights_var: Vec = pairing_rights_var - .into_iter() - .map(|p| IV::prepare_g2(&p).unwrap()) - .collect(); - let mut proofs_var = Vec::new(); - for p in proof.proofs.clone().into_iter() { - let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); - proofs_var.push(proof_var); - } - let pairing_lefts_var: Vec = proofs_var - .into_iter() - .map(|p| IV::prepare_g1(&p).unwrap()) - .collect(); - - let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var).unwrap(); - let right = IV::final_exponentiation(&right_ml).unwrap(); - - if () == left.enforce_equal(&right).unwrap() { - true - } else { - false - } -} +// fn check_2_gadget>( +// cs: ConstraintSystemRef, +// vk: VerifierKey, +// commitment: &CommitmentG2, +// point_var: &Vec::BaseField>>, +// value_var: FpVar<::BaseField>, +// proof: &ProofG1, +// ) -> bool +// where +// IV::G1Var: CurveVar, +// IV::G2Var: CurveVar, +// IV::GTVar: FieldVar, +// { +// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g)).unwrap(); +// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h)).unwrap(); +// let mut vk_gmask_var = Vec::new(); +// for g_mask in vk.g_mask_random.clone().into_iter() { +// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); +// vk_gmask_var.push(g_mask_var); +// } +// // allocate commitment +// let com_g2_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product)).unwrap(); + +// let pair_right_op = com_g2_prod_var +// - (vk_h_var +// .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) +// .unwrap()); +// let right_prepared = IV::prepare_g2(&pair_right_op).unwrap(); +// let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); +// let left = IV::pairing(left_prepared, right_prepared).unwrap(); + +// let mut h_mul_var = Vec::new(); + +// for p in point_var.into_iter() { +// let x = vk_h_var +// .scalar_mul_le(p.to_bits_le().unwrap().iter()) +// .unwrap(); +// h_mul_var.push(x); +// } +// let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); +// let mut h_mask_random_var = Vec::new(); +// for h_mask in h_mask_random.clone().into_iter() { +// let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask)).unwrap(); +// h_mask_random_var.push(h_mask_var); +// } +// let pairing_rights_var: Vec<_> = (0..vk.nv) +// .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) +// .collect(); +// let pairing_rights_var: Vec = pairing_rights_var +// .into_iter() +// .map(|p| IV::prepare_g2(&p).unwrap()) +// .collect(); +// let mut proofs_var = Vec::new(); +// for p in proof.proofs.clone().into_iter() { +// let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); +// proofs_var.push(proof_var); +// } +// let pairing_lefts_var: Vec = proofs_var +// .into_iter() +// .map(|p| IV::prepare_g1(&p).unwrap()) +// .collect(); + +// let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var).unwrap(); +// let right = IV::final_exponentiation(&right_ml).unwrap(); + +// if () == left.enforce_equal(&right).unwrap() { +// true +// } else { +// false +// } +// } -fn check_gadget>( - cs: ConstraintSystemRef, - vk: VerifierKey, - commitment: Commitment, - point_var: &Vec::BaseField>>, - value: E::ScalarField, - proof: Proof, -) -> Result -where - IV::G1Var: CurveVar, - IV::G2Var: CurveVar, - IV::GTVar: FieldVar, -{ - let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; - let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; - let mut vk_gmask_var = Vec::new(); - for g_mask in vk.g_mask_random.clone().into_iter() { - let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; - vk_gmask_var.push(g_mask_var); - } - // allocate commitment - let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; - // allocate value - let scalar_in_fq = &E::BaseField::from_bigint( - ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), - ) - .unwrap(); - let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - // allocate proof - let mut proofs_var = Vec::new(); - for proof in proof.proofs.clone().into_iter() { - let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; - proofs_var.push(proof_var); - } - // start operation on circuit - let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); - let left_prepared = IV::prepare_g1(&pair_left_op)?; - let right_prepared = IV::prepare_g2(&vk_h_var)?; - let left = IV::pairing(left_prepared, right_prepared)?; - - //calculating msm with framework function outside the circuit - // let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize; - // let window_size = FixedBase::get_mul_window_size(self.vk.nv); - - // let g_table = FixedBase::get_window_table(scalar_size, window_size, self.vk.g.into_group()); - // let g_mul: Vec = - // FixedBase::msm(scalar_size, window_size, &g_table, self.point.as_slice()); - - //calculate basic msm - // let mut res = Vec::new(); - // for s in point.into_iter() { - // res.push(vk.g.mul(s)); - // } - - //check basic msm with basic vector - //assert_eq!(res, g_mul); - - let mut res_var = Vec::new(); - - for p in point_var.into_iter() { - let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; - res_var.push(x); - } +// fn check_gadget>( +// cs: ConstraintSystemRef, +// vk: VerifierKey, +// commitment: Commitment, +// point_var: &Vec::BaseField>>, +// value: E::ScalarField, +// proof: Proof, +// ) -> Result +// where +// IV::G1Var: CurveVar, +// IV::G2Var: CurveVar, +// IV::GTVar: FieldVar, +// { +// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; +// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; +// let mut vk_gmask_var = Vec::new(); +// for g_mask in vk.g_mask_random.clone().into_iter() { +// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; +// vk_gmask_var.push(g_mask_var); +// } +// // allocate commitment +// let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; +// // allocate value +// let scalar_in_fq = &E::BaseField::from_bigint( +// ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), +// ) +// .unwrap(); +// let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// // allocate proof +// let mut proofs_var = Vec::new(); +// for proof in proof.proofs.clone().into_iter() { +// let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; +// proofs_var.push(proof_var); +// } +// // start operation on circuit +// let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); +// let left_prepared = IV::prepare_g1(&pair_left_op)?; +// let right_prepared = IV::prepare_g2(&vk_h_var)?; +// let left = IV::pairing(left_prepared, right_prepared)?; + +// //calculating msm with framework function outside the circuit +// // let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize; +// // let window_size = FixedBase::get_mul_window_size(self.vk.nv); + +// // let g_table = FixedBase::get_window_table(scalar_size, window_size, self.vk.g.into_group()); +// // let g_mul: Vec = +// // FixedBase::msm(scalar_size, window_size, &g_table, self.point.as_slice()); + +// //calculate basic msm +// // let mut res = Vec::new(); +// // for s in point.into_iter() { +// // res.push(vk.g.mul(s)); +// // } + +// //check basic msm with basic vector +// //assert_eq!(res, g_mul); + +// let mut res_var = Vec::new(); + +// for p in point_var.into_iter() { +// let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; +// res_var.push(x); +// } - //do msm with circuit variable - // let mut g_mul_var = Vec::new(); - // for g_m in g_mul.clone().into_iter() { - // let g_m_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_m))?; - // g_mul_var.push(g_m_var); - // } +// //do msm with circuit variable +// // let mut g_mul_var = Vec::new(); +// // for g_m in g_mul.clone().into_iter() { +// // let g_m_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_m))?; +// // g_mul_var.push(g_m_var); +// // } - //assert vector calculated with msm and allocated is equal to msm calculated locally with variable - //res_var.enforce_equal(&g_mul_var)?; +// //assert vector calculated with msm and allocated is equal to msm calculated locally with variable +// //res_var.enforce_equal(&g_mul_var)?; - //computing other part of the circuit - let pairing_lefts_var: Vec<_> = (0..vk.nv) - .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) - .collect(); +// //computing other part of the circuit +// let pairing_lefts_var: Vec<_> = (0..vk.nv) +// .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) +// .collect(); - let mut pairing_lefts_prep = Vec::new(); - for var in pairing_lefts_var.clone().into_iter() { - pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); - } +// let mut pairing_lefts_prep = Vec::new(); +// for var in pairing_lefts_var.clone().into_iter() { +// pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); +// } - let mut pairing_right_prep = Vec::new(); - for var in proofs_var.clone().into_iter() { - pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); - } +// let mut pairing_right_prep = Vec::new(); +// for var in proofs_var.clone().into_iter() { +// pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); +// } - let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; - let right = IV::final_exponentiation(&right_ml).unwrap(); - if () == left.enforce_equal(&right).unwrap() { - Ok(true) - } else { - Ok(false) - } -} +// let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; +// let right = IV::final_exponentiation(&right_ml).unwrap(); +// if () == left.enforce_equal(&right).unwrap() { +// Ok(true) +// } else { +// Ok(false) +// } +// } -#[cfg(test)] -mod tests { - use crate::ark_std::UniformRand; - use ark_bls12_377::{Bls12_377, Config, FqConfig}; - use ark_bls12_381::Bls12_381; - use ark_ec::pairing::Pairing; - use ark_ec::short_weierstrass::Affine; - use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; - use ark_std::rand::RngCore; - use ark_std::test_rng; - use ark_std::vec::Vec; - type E = Bls12_377; - use ark_relations::r1cs::ConstraintSystem; - type Fr = ::ScalarField; - use super::*; - use ark_ec::bls12::Bls12; - type IV = ark_bls12_377::constraints::PairingVar; - use crate::ark_std::rand::SeedableRng; - use ark_bw6_761::BW6_761 as P; - use ark_crypto_primitives::snark::SNARK; - use ark_ff::Field; - use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; - use ark_groth16::prepare_verifying_key; - use ark_groth16::Groth16; - type Fp = ::BaseField; - use super::*; - type F = ark_bls12_377::Fr; - use crate::parameters::poseidon_params; - use crate::sqrt_pst::Polynomial; - - #[test] - fn check_commit() { - // check odd case - check_sqrt_poly_commit(5); - } +// #[cfg(test)] +// mod tests { +// use crate::ark_std::UniformRand; +// use ark_bls12_377::{Bls12_377, Config, FqConfig}; +// use ark_bls12_381::Bls12_381; +// use ark_ec::pairing::Pairing; +// use ark_ec::short_weierstrass::Affine; +// use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; +// use ark_std::rand::RngCore; +// use ark_std::test_rng; +// use ark_std::vec::Vec; +// type E = Bls12_377; +// use ark_relations::r1cs::ConstraintSystem; +// type Fr = ::ScalarField; +// use super::*; +// use ark_ec::bls12::Bls12; +// type IV = ark_bls12_377::constraints::PairingVar; +// use crate::ark_std::rand::SeedableRng; +// use ark_bw6_761::BW6_761 as P; +// use ark_crypto_primitives::snark::SNARK; +// use ark_ff::Field; +// use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; +// use ark_groth16::prepare_verifying_key; +// use ark_groth16::Groth16; +// type Fp = ::BaseField; +// use super::*; +// type F = ark_bls12_377::Fr; +// use crate::parameters::poseidon_params; +// use crate::sqrt_pst::Polynomial; + +// #[test] +// fn check_commit() { +// // check odd case +// check_sqrt_poly_commit(5); +// } - fn check_sqrt_poly_commit(num_vars: u32) { - let mut rng = ark_std::test_rng(); - let len = 2_usize.pow(num_vars); - let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); - let r: Vec = (0..num_vars) - .into_iter() - .map(|_| F::rand(&mut rng)) - .collect(); +// fn check_sqrt_poly_commit(num_vars: u32) { +// let mut rng = ark_std::test_rng(); +// let len = 2_usize.pow(num_vars); +// let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); +// let r: Vec = (0..num_vars) +// .into_iter() +// .map(|_| F::rand(&mut rng)) +// .collect(); - let gens = MultilinearPC::::setup(3, &mut rng); - let (ck, vk) = MultilinearPC::::trim(&gens, 3); +// let gens = MultilinearPC::::setup(3, &mut rng); +// let (ck, vk) = MultilinearPC::::trim(&gens, 3); - let mut pl = Polynomial::from_evaluations(&Z.clone()); +// let mut pl = Polynomial::from_evaluations(&Z.clone()); - let v = pl.eval(&r); +// let v = pl.eval(&r); - let (comm_list, t) = pl.commit(&ck); +// let (comm_list, t) = pl.commit(&ck); - let params = poseidon_params(); - let mut prover_transcript = PoseidonTranscript::new(¶ms); +// let params = poseidon_params(); +// let mut prover_transcript = PoseidonTranscript::new(¶ms); - let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); +// let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let mut verifier_transcript = PoseidonTranscript::new(¶ms); +// let mut verifier_transcript = PoseidonTranscript::new(¶ms); - let circuit = TestudoCommVerifier { - vk, - U: u, - point: r, - v, - pst_proof, - mipp_proof, - T: t, - _iv: PhantomData::, - }; +// let circuit = TestudoCommVerifier { +// vk, +// U: u, +// point: r, +// v, +// pst_proof, +// mipp_proof, +// T: t, +// _iv: PhantomData::, +// }; - let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); - let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); - let opvk = Groth16::

::process_vk(&ovk).unwrap(); - let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); - let public_input = vec![]; - assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); - } -} +// let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); +// let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); +// let opvk = Groth16::

::process_vk(&ovk).unwrap(); +// let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); +// let public_input = vec![]; +// assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); +// } +// } diff --git a/src/lib.rs b/src/lib.rs index 44893a94..b059e296 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,9 +36,9 @@ mod timer; pub(crate) mod transcript; mod unipoly; -pub mod parameters; - +mod circuit_verifier; mod constraints; +pub mod parameters; pub mod poseidon_transcript; use core::cmp::max; From 8f860f0b2aae02399943b9a905107e17041abad3 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Fri, 17 Nov 2023 13:38:45 +0100 Subject: [PATCH 10/21] feat: try to test poseidon --- src/circuit_verifier.rs | 10 +-- src/lib.rs | 3 +- src/mipp.rs | 6 ++ src/poseidon_transcript.rs | 24 +++++ src/prova.rs | 177 +++++++++++++++++++++++++++++++++++++ src/prova2.rs | 176 ++++++++++++++++++++++++++++++++++++ 6 files changed, 387 insertions(+), 9 deletions(-) create mode 100644 src/prova.rs create mode 100644 src/prova2.rs diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index a2fc3954..e41febf8 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -158,7 +158,6 @@ where ); assert!(res_mipp.unwrap() == true); - println!("ZIO CANE 161"); let mut a_rev_var = a_var.to_vec().clone(); a_rev_var.reverse(); @@ -171,7 +170,6 @@ where self.pst_proof, ); assert!(res_var.unwrap() == true); - println!("ZIO CANE 174"); Ok(()) } } @@ -312,7 +310,6 @@ where let right = IV::final_exponentiation(&right_ml).unwrap(); left.enforce_equal(&right); // OK Ok(true) - } fn mipp_verify_gadget>( @@ -456,7 +453,6 @@ where ); let check_h = check_h_var.unwrap(); assert!(check_h.clone() == true); - println!("ZIO CANE 466"); let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; let final_u_var = final_a_var .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) @@ -473,13 +469,11 @@ where //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); assert!(check_t == true); - println!("ZIO CANE 487"); let check_u = true; - //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { - + //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { + assert!(check_u == true); - println!("ZIO CANE 497"); Ok(check_h & check_u) } #[cfg(test)] diff --git a/src/lib.rs b/src/lib.rs index b059e296..15de3687 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,8 @@ mod circuit_verifier; mod constraints; pub mod parameters; pub mod poseidon_transcript; - +mod prova; +mod prova2; use core::cmp::max; use errors::R1CSError; diff --git a/src/mipp.rs b/src/mipp.rs index 93f7a9c1..99438db8 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -139,6 +139,8 @@ impl MippProof { .map(|_| transcript.challenge_scalar::(b"random_point")) .collect(); + println!("Prover"); + println!("{}", rs[0]); let pst_proof_h = MultilinearPC::::open_g1(ck, &poly, &rs); Ok(MippProof { @@ -278,6 +280,8 @@ impl MippProof { rs.push(r); } + println!("Verifier 1"); + println!("{}", rs[0]); // Given p_h is structured as defined above, the verifier can compute // p_h(rs) by themselves in O(m) time let v = (0..m) @@ -285,6 +289,8 @@ impl MippProof { .map(|i| E::ScalarField::one() + rs[i].mul(xs_inv[m - i - 1]) - rs[i]) .product(); + println!("Verifier 2"); + println!("{}", rs[0]); let comm_h = CommitmentG2 { nv: m, h_product: proof.final_h, diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index f1c7a71c..4830fb21 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -24,6 +24,10 @@ impl Transcript for PoseidonTranscript { point .serialize_with_mode(&mut buf, Compress::Yes) .expect("serialization failed"); + println!("STAMPO VEC BYTE"); + for v in buf.clone() { + println!("{}", v); + } self.sponge.absorb(&buf); } @@ -92,6 +96,26 @@ impl PoseidonTranscript { g_t.serialize_with_mode(&mut bytes, Compress::Yes).unwrap(); self.append_bytes(b"", &bytes); } + + pub fn append_g1(&mut self, _label: &'static [u8], g_t: &E::G1Affine) + where + E: Pairing, + { + let mut bytes = Vec::new(); + g_t.serialize_with_mode(&mut bytes, Compress::Yes).unwrap(); + self.append_bytes(b"", &bytes); + } + pub fn append_point_g1(&mut self, _label: &'static [u8], point: &G) + where + G: CurveGroup, + { + let mut point_encoding = Vec::new(); + point + .serialize_with_mode(&mut point_encoding, Compress::Yes) + .unwrap(); + self.sponge.absorb(&point_encoding); + } + } pub trait TranscriptWriter { diff --git a/src/prova.rs b/src/prova.rs new file mode 100644 index 00000000..d8f32b1c --- /dev/null +++ b/src/prova.rs @@ -0,0 +1,177 @@ +use crate::ark_std::One; +use crate::ark_std::UniformRand; +use crate::mipp::MippProof; +use crate::parameters::get_bls12377_fq_params; +use crate::parameters::params_to_base_field; +use crate::{ + math::Math, + poseidon_transcript::PoseidonTranscript, + sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, + unipoly::UniPoly, +}; +use ark_bls12_377::g1::G1Affine; +use ark_bls12_377::Fr; +use ark_bls12_377::G1Projective; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::poseidon; +use ark_crypto_primitives::sponge::Absorb; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +use ark_crypto_primitives::Error; +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +use ark_poly_commit::multilinear_pc::{ + data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, + MultilinearPC, +}; +use ark_r1cs_std::groups::bls12::G1Var; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::{ + alloc::{AllocVar, AllocationMode}, + fields::fp::FpVar, + prelude::{EqGadget, FieldVar}, +}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::Compress; +use digest::generic_array::typenum::True; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::MulAssign; +use std::{borrow::Borrow, marker::PhantomData}; + +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + native_sponge: PoseidonTranscript, + constraint_sponge: PoseidonSpongeVar, + point: E::G1Affine, + scalar_in_fq: E::BaseField, + hash: E::BaseField, + _iv: PhantomData, +} + +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, +{ + fn generate_constraints( + mut self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + let exp_hash_var = FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); + + println!("EXP_HASH_VAR: "); + println!("{}", exp_hash_var.value().unwrap()); + //let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); + // self + // .constraint_sponge + // .clone() + // .absorb(&point_var_affine) + // .unwrap(); + + println!("SCALAR_FQ 2: "); + println!("{}", self.scalar_in_fq); + + let scalar_var = FpVar::new_witness(cs.clone(), || Ok(self.scalar_in_fq)).unwrap(); + + println!("SCALAR_VAR: "); + println!("{}", scalar_var.value().unwrap()); + self.constraint_sponge.absorb(&scalar_var).unwrap(); + + let hash_var = self + .constraint_sponge + .squeeze_field_elements(1) + .unwrap() + .remove(0); + + + println!("HASH_VAR: "); + println!("{}", hash_var.value().unwrap()); + + hash_var.enforce_equal(&exp_hash_var).unwrap(); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::parameters::get_bls12377_fq_params; + use ark_bls12_377::constraints::G1Var; + use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; + use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; + use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; + use ark_crypto_primitives::sponge::CryptographicSponge; + use ark_ec::bls12::Bls12; + use ark_ec::pairing::Pairing; + use ark_ff::{BigInteger, PrimeField}; + use ark_r1cs_std::{fields::fp::FpVar, groups::CurveVar, prelude::*}; + use ark_relations::{ns, r1cs::ConstraintSystem}; + use ark_std::test_rng; + use ark_std::UniformRand; + use crate::transcript::Transcript; + use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; + #[test] + fn absorb_test() { + let mut rng = test_rng(); + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + + let sponge_params = get_bls12377_fq_params(); + + let mut native_sponge = PoseidonTranscript::new(&sponge_params); + let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); + + let mut rng = ark_std::test_rng(); + let point = ark_bls12_377::G1Affine::rand(&mut rng); + let scalar = ark_bls12_377::Fr::rand(&mut rng); + let scalar_in_fq = + as Pairing>::BaseField::from_bigint(< as Pairing>::BaseField as PrimeField>::BigInt::from_bits_le( + scalar.into_bigint().to_bits_le().as_slice(), + )) + .unwrap(); + + //native_sponge.absorb(&point.clone()); + println!("SCALAR_FQ 1: "); + println!("{}", scalar_in_fq); + native_sponge.append_scalar(b"U",&scalar_in_fq); + + let hash = native_sponge.challenge_scalar::< as Pairing>::BaseField>(b"random_point"); + + println!("HASH: "); + println!("{}", hash); + + // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); + // constraint_sponge.absorb(&point_var_affine); + + // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); + // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); + // constraint_sponge.absorb(&scalar_var); + let circuit: TestudoCommVerifier< I, IV> = TestudoCommVerifier { + + native_sponge, + constraint_sponge, + point, + scalar_in_fq, + hash, + _iv: PhantomData, + }; + + circuit.generate_constraints(cs.clone()).unwrap(); + //let hash_var = constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); + //hash_var.enforce_equal(&exp_hash_var).unwrap(); + assert!(cs.is_satisfied().unwrap()); + } +} diff --git a/src/prova2.rs b/src/prova2.rs new file mode 100644 index 00000000..41ff62a9 --- /dev/null +++ b/src/prova2.rs @@ -0,0 +1,176 @@ +use crate::ark_std::One; +use crate::ark_std::UniformRand; +use crate::mipp::MippProof; +use crate::parameters::get_bls12377_fq_params; +use crate::parameters::params_to_base_field; +use crate::{ + math::Math, + poseidon_transcript::PoseidonTranscript, + sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, + unipoly::UniPoly, +}; +use ark_serialize::CanonicalSerialize; +use ark_bls12_377::g1::G1Affine; +use ark_bls12_377::Fr; +use ark_bls12_377::G1Projective; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::poseidon; +use ark_crypto_primitives::sponge::Absorb; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +use ark_crypto_primitives::Error; +use ark_ec::pairing::Pairing; +use ark_ec::AffineRepr; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +use ark_poly_commit::multilinear_pc::{ + data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, + MultilinearPC, +}; +use ark_r1cs_std::groups::bls12::G1Var; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::{ + alloc::{AllocVar, AllocationMode}, + fields::fp::FpVar, + prelude::{EqGadget, FieldVar}, +}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::Compress; +use digest::generic_array::typenum::True; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::MulAssign; +use std::{borrow::Borrow, marker::PhantomData}; + +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + native_sponge: PoseidonTranscript, + constraint_sponge: PoseidonSpongeVar, + point: E::G1Affine, + scalar_in_fq: E::BaseField, + hash: E::BaseField, + _iv: PhantomData, +} + +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + >::G1Var: AbsorbGadget<::BaseField> +{ + fn generate_constraints( + mut self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + let exp_hash_var = FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); + + println!("EXP_HASH_VAR: "); + println!("{}", exp_hash_var.value().unwrap()); + + + let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); + println!("POINT 2: "); + println!("{}", point_var_affine.value().unwrap()); + + // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(self.scalar_in_fq)).unwrap(); + + // println!("SCALAR_VAR: "); + // println!("{}", scalar_var.value().unwrap()); + + self.constraint_sponge.absorb(&point_var_affine.to_bits_be().unwrap()).unwrap(); + + let hash_var = self + .constraint_sponge + .squeeze_field_elements(1) + .unwrap() + .remove(0); + + + println!("HASH_VAR: "); + println!("{}", hash_var.value().unwrap()); + + hash_var.enforce_equal(&exp_hash_var).unwrap(); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::parameters::get_bls12377_fq_params; + use ark_bls12_377::constraints::G1Var; + use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; + use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; + use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; + use ark_crypto_primitives::sponge::CryptographicSponge; + use ark_ec::bls12::Bls12; + use ark_ec::pairing::Pairing; + use ark_ff::{BigInteger, PrimeField}; + use ark_r1cs_std::{fields::fp::FpVar, groups::CurveVar, prelude::*}; + use ark_relations::{ns, r1cs::ConstraintSystem}; + use ark_std::test_rng; + use ark_std::UniformRand; + use crate::transcript::Transcript; + use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; + #[test] + fn absorb_test() { + let mut rng = test_rng(); + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + + let sponge_params = get_bls12377_fq_params(); + + let mut native_sponge = PoseidonTranscript::new(&sponge_params); + let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); + + let mut rng = ark_std::test_rng(); + let point = ark_bls12_377::G1Affine::rand(&mut rng); + let scalar = ark_bls12_377::Fr::rand(&mut rng); + let scalar_in_fq = + as Pairing>::BaseField::from_bigint(< as Pairing>::BaseField as PrimeField>::BigInt::from_bits_le( + scalar.into_bigint().to_bits_le().as_slice(), + )) + .unwrap(); + + //native_sponge.absorb(&point.clone()); + println!("POINT 1: "); + println!("{}", point); + native_sponge.append(b"U",&point); + + let hash = native_sponge.challenge_scalar::< as Pairing>::BaseField>(b"random_point"); + + println!("HASH: "); + println!("{}", hash); + + // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); + // constraint_sponge.absorb(&point_var_affine); + + // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); + // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); + // constraint_sponge.absorb(&scalar_var); + let circuit: TestudoCommVerifier< I, IV> = TestudoCommVerifier { + + native_sponge, + constraint_sponge, + point, + scalar_in_fq, + hash, + _iv: PhantomData, + }; + + circuit.generate_constraints(cs.clone()).unwrap(); + //let hash_var = constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); + //hash_var.enforce_equal(&exp_hash_var).unwrap(); + assert!(cs.is_satisfied().unwrap()); + } +} From 8e6e986d7c44a345c0a58a43d18611c9d9feaecb Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Fri, 17 Nov 2023 14:10:24 +0100 Subject: [PATCH 11/21] feat: add print vec byte --- src/poseidon_transcript.rs | 6 +++--- src/prova.rs | 20 ++++++++++---------- src/prova2.rs | 37 ++++++++++++++++++++++--------------- src/sqrt_pst.rs | 2 +- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index 4830fb21..55817d7d 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -22,12 +22,13 @@ impl Transcript for PoseidonTranscript { fn append(&mut self, _label: &'static [u8], point: &S) { let mut buf = Vec::new(); point - .serialize_with_mode(&mut buf, Compress::Yes) + .serialize_with_mode(&mut buf, Compress::No) .expect("serialization failed"); println!("STAMPO VEC BYTE"); for v in buf.clone() { - println!("{}", v); + print!("{} - ", v); } + println!(); self.sponge.absorb(&buf); } @@ -115,7 +116,6 @@ impl PoseidonTranscript { .unwrap(); self.sponge.absorb(&point_encoding); } - } pub trait TranscriptWriter { diff --git a/src/prova.rs b/src/prova.rs index d8f32b1c..8a4a9f3a 100644 --- a/src/prova.rs +++ b/src/prova.rs @@ -69,7 +69,8 @@ where mut self, cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { - let exp_hash_var = FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); + let exp_hash_var = + FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); println!("EXP_HASH_VAR: "); println!("{}", exp_hash_var.value().unwrap()); @@ -95,7 +96,6 @@ where .unwrap() .remove(0); - println!("HASH_VAR: "); println!("{}", hash_var.value().unwrap()); @@ -108,7 +108,9 @@ where mod tests { use super::*; use crate::parameters::get_bls12377_fq_params; + use crate::transcript::Transcript; use ark_bls12_377::constraints::G1Var; + use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; @@ -120,8 +122,6 @@ mod tests { use ark_relations::{ns, r1cs::ConstraintSystem}; use ark_std::test_rng; use ark_std::UniformRand; - use crate::transcript::Transcript; - use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; #[test] fn absorb_test() { let mut rng = test_rng(); @@ -143,24 +143,24 @@ mod tests { )) .unwrap(); - //native_sponge.absorb(&point.clone()); + //native_sponge.absorb(&point.clone()); println!("SCALAR_FQ 1: "); println!("{}", scalar_in_fq); - native_sponge.append_scalar(b"U",&scalar_in_fq); + native_sponge.append_scalar(b"U", &scalar_in_fq); - let hash = native_sponge.challenge_scalar::< as Pairing>::BaseField>(b"random_point"); + let hash = native_sponge + .challenge_scalar::< as Pairing>::BaseField>(b"random_point"); println!("HASH: "); println!("{}", hash); // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); // constraint_sponge.absorb(&point_var_affine); - + // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); // constraint_sponge.absorb(&scalar_var); - let circuit: TestudoCommVerifier< I, IV> = TestudoCommVerifier { - + let circuit: TestudoCommVerifier = TestudoCommVerifier { native_sponge, constraint_sponge, point, diff --git a/src/prova2.rs b/src/prova2.rs index 41ff62a9..9379fbec 100644 --- a/src/prova2.rs +++ b/src/prova2.rs @@ -9,7 +9,6 @@ use crate::{ sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, }; -use ark_serialize::CanonicalSerialize; use ark_bls12_377::g1::G1Affine; use ark_bls12_377::Fr; use ark_bls12_377::G1Projective; @@ -40,6 +39,7 @@ use ark_r1cs_std::{ prelude::{EqGadget, FieldVar}, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; use digest::generic_array::typenum::True; use std::ops::AddAssign; @@ -65,18 +65,18 @@ where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, - >::G1Var: AbsorbGadget<::BaseField> + >::G1Var: AbsorbGadget<::BaseField>, { fn generate_constraints( mut self, cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { - let exp_hash_var = FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); + let exp_hash_var = + FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); println!("EXP_HASH_VAR: "); println!("{}", exp_hash_var.value().unwrap()); - let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); println!("POINT 2: "); println!("{}", point_var_affine.value().unwrap()); @@ -85,8 +85,16 @@ where // println!("SCALAR_VAR: "); // println!("{}", scalar_var.value().unwrap()); - - self.constraint_sponge.absorb(&point_var_affine.to_bits_be().unwrap()).unwrap(); + let prova = &point_var_affine.to_bytes().unwrap(); + println!("STAMPO VEC BYTE CIRCUIT"); + for v in prova.clone() { + print!("{} - ", v.value().unwrap()); + } + println!(); + self + .constraint_sponge + .absorb(&point_var_affine.to_bytes().unwrap()) + .unwrap(); let hash_var = self .constraint_sponge @@ -94,7 +102,6 @@ where .unwrap() .remove(0); - println!("HASH_VAR: "); println!("{}", hash_var.value().unwrap()); @@ -107,7 +114,9 @@ where mod tests { use super::*; use crate::parameters::get_bls12377_fq_params; + use crate::transcript::Transcript; use ark_bls12_377::constraints::G1Var; + use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; @@ -119,8 +128,6 @@ mod tests { use ark_relations::{ns, r1cs::ConstraintSystem}; use ark_std::test_rng; use ark_std::UniformRand; - use crate::transcript::Transcript; - use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; #[test] fn absorb_test() { let mut rng = test_rng(); @@ -142,24 +149,24 @@ mod tests { )) .unwrap(); - //native_sponge.absorb(&point.clone()); + //native_sponge.absorb(&point.clone()); println!("POINT 1: "); println!("{}", point); - native_sponge.append(b"U",&point); + native_sponge.append(b"U", &point); - let hash = native_sponge.challenge_scalar::< as Pairing>::BaseField>(b"random_point"); + let hash = native_sponge + .challenge_scalar::< as Pairing>::BaseField>(b"random_point"); println!("HASH: "); println!("{}", hash); // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); // constraint_sponge.absorb(&point_var_affine); - + // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); // constraint_sponge.absorb(&scalar_var); - let circuit: TestudoCommVerifier< I, IV> = TestudoCommVerifier { - + let circuit: TestudoCommVerifier = TestudoCommVerifier { native_sponge, constraint_sponge, point, diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index e4aec374..a513f6d9 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -300,7 +300,7 @@ mod tests { check_sqrt_poly_commit(5); // check even case - check_sqrt_poly_commit(6); + //check_sqrt_poly_commit(6); } fn check_sqrt_poly_commit(num_vars: u32) { From 2a969c52e5100da725c882ba2eea7ec4b4ea18db Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Sun, 19 Nov 2023 11:38:05 +0100 Subject: [PATCH 12/21] feat: add absorb made with bytes --- src/circuit_verifier.rs | 90 ++++++++++++++++++++---- src/mipp.rs | 3 + src/poseidon_transcript.rs | 5 -- src/prova.rs | 137 ++++++++++++++++++------------------- src/prova2.rs | 60 ++++++++++++++-- 5 files changed, 198 insertions(+), 97 deletions(-) diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index e41febf8..3d48f1e1 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -32,6 +32,7 @@ use ark_r1cs_std::{ prelude::{EqGadget, FieldVar}, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; use digest::generic_array::typenum::True; use std::ops::AddAssign; @@ -240,7 +241,7 @@ where let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var)?; let right = IV::final_exponentiation(&right_ml)?; - //left.enforce_equal(&right).unwrap(); + left.enforce_equal(&right).unwrap(); Ok(true) } @@ -358,7 +359,20 @@ where let params: PoseidonConfig = params_to_base_field::(); let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); - let U_g_product_var_bytes = U_g_product_var.to_bytes()?; + // PRIMA ABSORB + let mut U_g_product_buf = Vec::new(); + U_g_product_var + .value() + .unwrap() + .serialize_with_mode(&mut U_g_product_buf, Compress::No) + .expect("serialization failed"); + + let mut U_g_product_var_bytes = Vec::new(); + + for b in U_g_product_buf { + U_g_product_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + } + transcript_var.absorb(&U_g_product_var_bytes)?; let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; @@ -366,20 +380,69 @@ where let (comm_u_l, comm_u_r) = comm_u; let (comm_t_l, comm_t_r) = comm_t; // Fiat-Shamir challenge + // ABSORB COMM_U_R + let mut comm_u_l_buf = Vec::new(); + comm_u_l + .value() + .unwrap() + .serialize_with_mode(&mut comm_u_l_buf, Compress::No) + .expect("serialization failed"); + + let mut comm_u_l_var_bytes = Vec::new(); + + for b in comm_u_l_buf { + comm_u_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + } + transcript_var.absorb(&comm_u_l_var_bytes)?; + // ABSORB COMM_U_R + let mut comm_u_r_buf = Vec::new(); + comm_u_r + .value() + .unwrap() + .serialize_with_mode(&mut comm_u_r_buf, Compress::No) + .expect("serialization failed"); + + let mut comm_u_r_var_bytes = Vec::new(); + + for b in comm_u_r_buf { + comm_u_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + } + transcript_var.absorb(&comm_u_r_var_bytes)?; + // ABSORB COMM_T_L + let mut comm_t_l_buf = Vec::new(); + comm_t_l + .value() + .unwrap() + .serialize_with_mode(&mut comm_t_l_buf, Compress::No) + .expect("serialization failed"); + + let mut comm_t_l_var_bytes = Vec::new(); + + for b in comm_t_l_buf { + comm_t_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + } + transcript_var.absorb(&comm_t_l_var_bytes)?; + // ABSORB COMM_T_R + let mut comm_t_r_buf = Vec::new(); + comm_t_r + .value() + .unwrap() + .serialize_with_mode(&mut comm_t_r_buf, Compress::No) + .expect("serialization failed"); + + let mut comm_t_r_var_bytes = Vec::new(); + + for b in comm_t_r_buf { + comm_t_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + } + transcript_var.absorb(&comm_t_r_var_bytes)?; - let comm_u_l_bytes = comm_u_l.to_bytes()?; - let comm_u_r_bytes = comm_u_r.to_bytes()?; - transcript_var.absorb(&comm_u_l_bytes)?; - transcript_var.absorb(&comm_u_r_bytes)?; - // ATTENTION - let comm_t_l_bytes = comm_t_l.to_bytes()?; - transcript_var.absorb(&comm_t_l_bytes)?; - let comm_t_r_bytes = comm_t_r.to_bytes()?; - transcript_var.absorb(&comm_t_r_bytes)?; - // transcript_var.absorb(comm_t_r); let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); let c_var = c_inv_var.inverse().unwrap(); + println!("PRIMA SQUEEZY CIRCUIT"); + println!("{}", c_inv_var.value().unwrap()); + break; xs.push(c_var.clone()); xs_inv.push(c_inv_var.clone()); @@ -431,7 +494,8 @@ where let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); rs.push(r); } - + println!("SONO QUA"); + println!("{}", rs[0].value().unwrap()); // let rs_var = rs.clone(); let v_var: FpVar<::BaseField> = (0..m) .into_iter() diff --git a/src/mipp.rs b/src/mipp.rs index 99438db8..54b42a00 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -213,6 +213,9 @@ impl MippProof { transcript.append(b"comm_t_l", comm_t_l); transcript.append(b"comm_t_r", comm_t_r); let c_inv = transcript.challenge_scalar::(b"challenge_i"); + println!("PRIMA SQUEEZY NAIVE"); + println!("{}", c_inv); + break; let c = c_inv.inverse().unwrap(); xs.push(c); diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index 55817d7d..74554c54 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -24,11 +24,6 @@ impl Transcript for PoseidonTranscript { point .serialize_with_mode(&mut buf, Compress::No) .expect("serialization failed"); - println!("STAMPO VEC BYTE"); - for v in buf.clone() { - print!("{} - ", v); - } - println!(); self.sponge.absorb(&buf); } diff --git a/src/prova.rs b/src/prova.rs index 8a4a9f3a..bc7c7dd1 100644 --- a/src/prova.rs +++ b/src/prova.rs @@ -1,50 +1,23 @@ -use crate::ark_std::One; -use crate::ark_std::UniformRand; -use crate::mipp::MippProof; -use crate::parameters::get_bls12377_fq_params; use crate::parameters::params_to_base_field; -use crate::{ - math::Math, - poseidon_transcript::PoseidonTranscript, - sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, - unipoly::UniPoly, -}; -use ark_bls12_377::g1::G1Affine; -use ark_bls12_377::Fr; -use ark_bls12_377::G1Projective; +use crate::poseidon_transcript::PoseidonTranscript; use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::poseidon; -use ark_crypto_primitives::sponge::Absorb; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -use ark_crypto_primitives::Error; use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; -use ark_poly_commit::multilinear_pc::data_structures::ProofG1; -use ark_poly_commit::multilinear_pc::{ - data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, - MultilinearPC, -}; -use ark_r1cs_std::groups::bls12::G1Var; use ark_r1cs_std::prelude::*; use ark_r1cs_std::{ - alloc::{AllocVar, AllocationMode}, + alloc::AllocVar, fields::fp::FpVar, - prelude::{EqGadget, FieldVar}, + prelude::EqGadget, }; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; -use digest::generic_array::typenum::True; -use std::ops::AddAssign; -use std::ops::Mul; -use std::ops::MulAssign; -use std::{borrow::Borrow, marker::PhantomData}; +use std::marker::PhantomData; + struct TestudoCommVerifier where @@ -64,34 +37,67 @@ where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, + >::G1Var: AbsorbGadget<::BaseField>, { fn generate_constraints( mut self, cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { - let exp_hash_var = - FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); + + + let params: PoseidonConfig = params_to_base_field::(); + + let mut buf = Vec::new(); + self.point + .serialize_with_mode(&mut buf, Compress::No) + .expect("serialization failed"); + + let mut sponge_naive = PoseidonSponge::::new(¶ms); + + let mut sponge_var = PoseidonSpongeVar::::new(cs.clone(),¶ms); - println!("EXP_HASH_VAR: "); - println!("{}", exp_hash_var.value().unwrap()); - //let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); - // self - // .constraint_sponge - // .clone() - // .absorb(&point_var_affine) - // .unwrap(); + sponge_naive.absorb(&buf); - println!("SCALAR_FQ 2: "); - println!("{}", self.scalar_in_fq); + let real_hash: E::BaseField = sponge_naive.squeeze_field_elements(1).remove(0); - let scalar_var = FpVar::new_witness(cs.clone(), || Ok(self.scalar_in_fq)).unwrap(); + println!("REAL HASH "); + println!("{}", real_hash); - println!("SCALAR_VAR: "); - println!("{}", scalar_var.value().unwrap()); - self.constraint_sponge.absorb(&scalar_var).unwrap(); - let hash_var = self - .constraint_sponge + let real_hash_var = FpVar::new_input(cs.clone(), || Ok(real_hash)).unwrap(); + + println!("REAL HASH VAR"); + println!("{}", real_hash_var.value().unwrap()); + + let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); + + //start allocation for absorb + let mut buf2 = Vec::new(); + point_var_affine.value().unwrap() + .serialize_with_mode(&mut buf2, Compress::No) + .expect("serialization failed"); + + let mut x_var_vec = Vec::new(); + + for x in buf2 { + x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + } + //end allocation for absorb + + println!(); + println!("STAMPO BYTE DI VARIABILI"); + for v in x_var_vec.clone() { + print!("{} - ", v.value()?); + } + println!(); + + + sponge_var + .absorb(&x_var_vec) + .unwrap(); + + + let hash_var = sponge_var .squeeze_field_elements(1) .unwrap() .remove(0); @@ -99,7 +105,7 @@ where println!("HASH_VAR: "); println!("{}", hash_var.value().unwrap()); - hash_var.enforce_equal(&exp_hash_var).unwrap(); + hash_var.enforce_equal(&real_hash_var).unwrap(); Ok(()) } } @@ -109,17 +115,13 @@ mod tests { use super::*; use crate::parameters::get_bls12377_fq_params; use crate::transcript::Transcript; - use ark_bls12_377::constraints::G1Var; - use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; + use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; - use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; - use ark_crypto_primitives::sponge::CryptographicSponge; use ark_ec::bls12::Bls12; use ark_ec::pairing::Pairing; use ark_ff::{BigInteger, PrimeField}; - use ark_r1cs_std::{fields::fp::FpVar, groups::CurveVar, prelude::*}; - use ark_relations::{ns, r1cs::ConstraintSystem}; + use ark_relations::r1cs::ConstraintSystem; use ark_std::test_rng; use ark_std::UniformRand; #[test] @@ -143,10 +145,8 @@ mod tests { )) .unwrap(); - //native_sponge.absorb(&point.clone()); - println!("SCALAR_FQ 1: "); - println!("{}", scalar_in_fq); - native_sponge.append_scalar(b"U", &scalar_in_fq); + + native_sponge.append(b"U", &point); let hash = native_sponge .challenge_scalar::< as Pairing>::BaseField>(b"random_point"); @@ -154,12 +154,6 @@ mod tests { println!("HASH: "); println!("{}", hash); - // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); - // constraint_sponge.absorb(&point_var_affine); - - // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); - // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); - // constraint_sponge.absorb(&scalar_var); let circuit: TestudoCommVerifier = TestudoCommVerifier { native_sponge, constraint_sponge, @@ -170,8 +164,7 @@ mod tests { }; circuit.generate_constraints(cs.clone()).unwrap(); - //let hash_var = constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); - //hash_var.enforce_equal(&exp_hash_var).unwrap(); + ; assert!(cs.is_satisfied().unwrap()); } -} +} \ No newline at end of file diff --git a/src/prova2.rs b/src/prova2.rs index 9379fbec..8f28ee84 100644 --- a/src/prova2.rs +++ b/src/prova2.rs @@ -23,6 +23,7 @@ use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSpong use ark_crypto_primitives::Error; use ark_ec::pairing::Pairing; use ark_ec::AffineRepr; +use ark_ec::CurveGroup; use ark_ff::BigInteger; use ark_ff::PrimeField; use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; @@ -46,7 +47,6 @@ use std::ops::AddAssign; use std::ops::Mul; use std::ops::MulAssign; use std::{borrow::Borrow, marker::PhantomData}; - struct TestudoCommVerifier where E: Pairing, @@ -85,16 +85,62 @@ where // println!("SCALAR_VAR: "); // println!("{}", scalar_var.value().unwrap()); + // let x1 = point_var_affine.value().unwrap().into_affine().x().unwrap(); + // let y1 = point_var_affine.value().unwrap().into_affine().y().unwrap(); + // println!("X: "); + // println!("{}", x1); + // println!("Y: "); + // println!("{}", y1); + // let mut buf = Vec::new(); + // x1 + // .serialize_with_mode(&mut buf, Compress::No) + // .expect("serialization failed"); + + // println!("STAMPO VEC BYTE X1"); + // for v in buf.clone() { + // print!("{} - ", v); + // } + + // println!(""); + + // let mut buf2 = Vec::new(); + // y1 + // .serialize_with_mode(&mut buf2, Compress::No) + // .expect("serialization failed"); + + println!("STAMPO VEC BYTE"); let prova = &point_var_affine.to_bytes().unwrap(); - println!("STAMPO VEC BYTE CIRCUIT"); for v in prova.clone() { print!("{} - ", v.value().unwrap()); } - println!(); - self - .constraint_sponge - .absorb(&point_var_affine.to_bytes().unwrap()) - .unwrap(); + + // println!("ULTIMA PROVA"); + + // let mut buf3 = Vec::new(); + // point_var_affine.value().unwrap() + // .serialize_with_mode(&mut buf3, Compress::No) + // .expect("serialization failed"); + // println!("STAMPO VEC SERIALIZE CIRCUIT"); + // for v in buf3.clone() { + // print!("{} - ", v); + // } + // println!(); + // let prova = point_var_affine.to_bytes()?; + // let vec2 = Vec::new(); + // for v in buf3.clone() { + // vec2.push(UInt8::); + // } + let mut bits = point_var_affine.to_bits_le()?; + let bytes: Vec> = bits + .chunks(8) + .map(|chunk| UInt8::from_bits_le(chunk)) + .collect(); + + println!("STAMPO VEC SERIALIZE CIRCUIT"); + for v in bytes.clone() { + print!("{} - ", v.value().unwrap()); + } + self.constraint_sponge.absorb(&bytes).unwrap(); let hash_var = self .constraint_sponge From 8b586f5876f21050324c4238e62f8c1b042d01f2 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Mon, 27 Nov 2023 11:02:20 +0100 Subject: [PATCH 13/21] feat: add groth16 verifier inside the circuit --- Cargo.toml | 4 +- benches/testudo.rs | 256 +++++++++--------- examples/cubic.rs | 342 ++++++++++++------------ profiler/testudo.rs | 162 ++++++------ src/circuit_verifier.rs | 141 +++++----- src/constraints.rs | 564 +--------------------------------------- src/lib.rs | 15 +- src/mipp.rs | 13 +- src/parameters.rs | 31 +++ src/prova.rs | 222 ++++++++-------- src/prova2.rs | 426 ++++++++++++++---------------- src/prova3.rs | 198 ++++++++++++++ src/r1csproof.rs | 86 +++--- src/sqrt_pst.rs | 2 +- src/verifier_circuit.rs | 150 +++++++++++ 15 files changed, 1232 insertions(+), 1380 deletions(-) create mode 100644 src/prova3.rs create mode 100644 src/verifier_circuit.rs diff --git a/Cargo.toml b/Cargo.toml index dbfec1c8..8ad4f6c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,11 +25,11 @@ ark-bls12-377 = { version = "0.4.0", features = ["r1cs","curve"] } ark-bls12-381 = { version = "0.4.0", features = ["curve"] } ark-blst = { git = "https://github.com/nikkolasg/ark-blst" } ark-serialize = { version = "0.4.0", features = ["derive"] } -ark-crypto-primitives = {version = "0.4.0", features = ["sponge","r1cs","snark"] } +ark-crypto-primitives = {version = "^0.4.0", features = ["sponge","r1cs","snark"] } ark-r1cs-std = { version = "0.4.0", default-features = false } ark-relations = { version = "0.4.0", default-features = false, optional = true } ark-snark = { version = "0.4.0", default-features = false } -ark-groth16 = { version = "0.4.0" } +ark-groth16 = { version = "0.4.0", features = ["r1cs"] } ark-bw6-761 = { version = "0.4.0" } ark-poly-commit = { version = "0.4.0" } ark-poly = {version = "0.4.0"} diff --git a/benches/testudo.rs b/benches/testudo.rs index bd9cc75a..9873d9b7 100644 --- a/benches/testudo.rs +++ b/benches/testudo.rs @@ -1,127 +1,129 @@ -use std::time::Instant; - -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use ark_ec::pairing::Pairing; -use ark_ff::PrimeField; -use ark_serialize::*; -use libtestudo::parameters::PoseidonConfiguration; -use libtestudo::{ - poseidon_transcript::PoseidonTranscript, - testudo_snark::{TestudoSnark, TestudoSnarkGens}, - Instance, -}; -use serde::Serialize; - -#[derive(Default, Clone, Serialize)] -struct BenchmarkResults { - power: usize, - input_constraints: usize, - testudo_proving_time: u128, - testudo_verification_time: u128, - sat_proof_size: usize, - eval_proof_size: usize, - total_proof_size: usize, -} - -fn main() { - bench_with_bls12_377(); - // bench_with_bls12_381(); - // bench_with_ark_blst(); -} - -fn bench_with_ark_blst() { - let params = ark_blst::Scalar::poseidon_params(); - testudo_snark_bench::(params, "testudo_blst"); -} - -fn bench_with_bls12_377() { - let params = ark_bls12_377::Fr::poseidon_params(); - testudo_snark_bench::(params, "testudo_bls12_377"); -} - -fn bench_with_bls12_381() { - let params = ark_bls12_381::Fr::poseidon_params(); - testudo_snark_bench::(params, "testudo_bls12_381"); -} - -fn testudo_snark_bench(params: PoseidonConfig, file_name: &str) -where - E: Pairing, - E::ScalarField: PrimeField, - E::ScalarField: Absorb, -{ - let mut writer = csv::Writer::from_path(file_name).expect("unable to open csv writer"); - for &s in [4, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26].iter() { - println!("Running for {} inputs", s); - let mut br = BenchmarkResults::default(); - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - br.power = s; - br.input_constraints = num_cons; - let num_inputs = 10; - - let (inst, vars, inputs) = - Instance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); - - let gens = - TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, params.clone()); - - let (comm, decomm) = TestudoSnark::::encode(&inst, &gens); - - let start = Instant::now(); - let proof = TestudoSnark::prove( - &inst, - &comm, - &decomm, - vars, - &inputs, - &gens, - &mut prover_transcript, - params.clone(), - ) - .unwrap(); - let duration = start.elapsed().as_millis(); - br.testudo_proving_time = duration; - - let mut sat_proof = Vec::::new(); - proof - .r1cs_verifier_proof - .serialize_with_mode(&mut sat_proof, Compress::Yes) - .unwrap(); - br.sat_proof_size = sat_proof.len(); - - let mut eval_proof = Vec::::new(); - proof - .r1cs_eval_proof - .serialize_with_mode(&mut eval_proof, Compress::Yes) - .unwrap(); - br.eval_proof_size = eval_proof.len(); - - let mut total_proof = Vec::::new(); - proof - .serialize_with_mode(&mut total_proof, Compress::Yes) - .unwrap(); - br.total_proof_size = total_proof.len(); - - let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); - let start = Instant::now(); - - let res = proof.verify( - &gens, - &comm, - &inputs, - &mut verifier_transcript, - params.clone(), - ); - assert!(res.is_ok()); - let duration = start.elapsed().as_millis(); - br.testudo_verification_time = duration; - - writer - .serialize(br) - .expect("unable to write results to csv"); - writer.flush().expect("wasn't able to flush"); - } -} +// use std::time::Instant; + +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; +// use ark_ff::PrimeField; +// use ark_serialize::*; +// use libtestudo::parameters::PoseidonConfiguration; +// use libtestudo::{ +// poseidon_transcript::PoseidonTranscript, +// testudo_snark::{TestudoSnark, TestudoSnarkGens}, +// Instance, +// }; +// use serde::Serialize; + +// #[derive(Default, Clone, Serialize)] +// struct BenchmarkResults { +// power: usize, +// input_constraints: usize, +// testudo_proving_time: u128, +// testudo_verification_time: u128, +// sat_proof_size: usize, +// eval_proof_size: usize, +// total_proof_size: usize, +// } + +// fn main() { +// bench_with_bls12_377(); +// // bench_with_bls12_381(); +// // bench_with_ark_blst(); +// } + +// fn bench_with_ark_blst() { +// let params = ark_blst::Scalar::poseidon_params(); +// testudo_snark_bench::(params, "testudo_blst"); +// } + +// fn bench_with_bls12_377() { +// let params = ark_bls12_377::Fr::poseidon_params(); +// testudo_snark_bench::(params, "testudo_bls12_377"); +// } + +// fn bench_with_bls12_381() { +// let params = ark_bls12_381::Fr::poseidon_params(); +// testudo_snark_bench::(params, "testudo_bls12_381"); +// } + +// fn testudo_snark_bench(params: PoseidonConfig, file_name: &str) +// where +// E: Pairing, +// E::ScalarField: PrimeField, +// E::ScalarField: Absorb, +// { +// let mut writer = csv::Writer::from_path(file_name).expect("unable to open csv writer"); +// for &s in [4, 5, 10, 12, 14, 16, 18, 20, 22, 24, 26].iter() { +// println!("Running for {} inputs", s); +// let mut br = BenchmarkResults::default(); +// let num_vars = (2_usize).pow(s as u32); +// let num_cons = num_vars; +// br.power = s; +// br.input_constraints = num_cons; +// let num_inputs = 10; + +// let (inst, vars, inputs) = +// Instance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); +// let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); + +// let gens = +// TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, params.clone()); + +// let (comm, decomm) = TestudoSnark::::encode(&inst, &gens); + +// let start = Instant::now(); +// let proof = TestudoSnark::prove( +// &inst, +// &comm, +// &decomm, +// vars, +// &inputs, +// &gens, +// &mut prover_transcript, +// params.clone(), +// ) +// .unwrap(); +// let duration = start.elapsed().as_millis(); +// br.testudo_proving_time = duration; + +// let mut sat_proof = Vec::::new(); +// proof +// .r1cs_verifier_proof +// .serialize_with_mode(&mut sat_proof, Compress::Yes) +// .unwrap(); +// br.sat_proof_size = sat_proof.len(); + +// let mut eval_proof = Vec::::new(); +// proof +// .r1cs_eval_proof +// .serialize_with_mode(&mut eval_proof, Compress::Yes) +// .unwrap(); +// br.eval_proof_size = eval_proof.len(); + +// let mut total_proof = Vec::::new(); +// proof +// .serialize_with_mode(&mut total_proof, Compress::Yes) +// .unwrap(); +// br.total_proof_size = total_proof.len(); + +// let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); +// let start = Instant::now(); + +// let res = proof.verify( +// &gens, +// &comm, +// &inputs, +// &mut verifier_transcript, +// params.clone(), +// ); +// assert!(res.is_ok()); +// let duration = start.elapsed().as_millis(); +// br.testudo_verification_time = duration; + +// writer +// .serialize(br) +// .expect("unable to write results to csv"); +// writer.flush().expect("wasn't able to flush"); +// } +// } + +fn main() {} diff --git a/examples/cubic.rs b/examples/cubic.rs index dcc69eb5..34f16acc 100644 --- a/examples/cubic.rs +++ b/examples/cubic.rs @@ -1,170 +1,172 @@ -//! Demonstrates how to produces a proof for canonical cubic equation: `x^3 + x + 5 = y`. -//! The example is described in detail [here]. -//! -//! The R1CS for this problem consists of the following 4 constraints: -//! `Z0 * Z0 - Z1 = 0` -//! `Z1 * Z0 - Z2 = 0` -//! `(Z2 + Z0) * 1 - Z3 = 0` -//! `(Z3 + 5) * 1 - I0 = 0` -//! -//! [here]: https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649 -use ark_ec::pairing::Pairing; -use ark_ff::{BigInteger, PrimeField}; -use ark_std::{One, UniformRand, Zero}; -use libtestudo::testudo_snark::{TestudoSnark, TestudoSnarkGens}; -use libtestudo::{ - parameters::poseidon_params, poseidon_transcript::PoseidonTranscript, InputsAssignment, Instance, - VarsAssignment, -}; - -#[allow(non_snake_case)] -fn produce_r1cs() -> ( - usize, - usize, - usize, - usize, - Instance, - VarsAssignment, - InputsAssignment, -) { - // parameters of the R1CS instance - let num_cons = 4; - let num_vars = 4; - let num_inputs = 1; - let num_non_zero_entries = 8; - - // We will encode the above constraints into three matrices, where - // the coefficients in the matrix are in the little-endian byte order - let mut A: Vec<(usize, usize, Vec)> = Vec::new(); - let mut B: Vec<(usize, usize, Vec)> = Vec::new(); - let mut C: Vec<(usize, usize, Vec)> = Vec::new(); - - let one = E::ScalarField::one().into_bigint().to_bytes_le(); - - // R1CS is a set of three sparse matrices A B C, where is a row for every - // constraint and a column for every entry in z = (vars, 1, inputs) - // An R1CS instance is satisfiable iff: - // Az \circ Bz = Cz, where z = (vars, 1, inputs) - - // constraint 0 entries in (A,B,C) - // constraint 0 is Z0 * Z0 - Z1 = 0. - A.push((0, 0, one.clone())); - B.push((0, 0, one.clone())); - C.push((0, 1, one.clone())); - - // constraint 1 entries in (A,B,C) - // constraint 1 is Z1 * Z0 - Z2 = 0. - A.push((1, 1, one.clone())); - B.push((1, 0, one.clone())); - C.push((1, 2, one.clone())); - - // constraint 2 entries in (A,B,C) - // constraint 2 is (Z2 + Z0) * 1 - Z3 = 0. - A.push((2, 2, one.clone())); - A.push((2, 0, one.clone())); - B.push((2, num_vars, one.clone())); - C.push((2, 3, one.clone())); - - // constraint 3 entries in (A,B,C) - // constraint 3 is (Z3 + 5) * 1 - I0 = 0. - A.push((3, 3, one.clone())); - A.push(( - 3, - num_vars, - E::ScalarField::from(5u32).into_bigint().to_bytes_le(), - )); - B.push((3, num_vars, one.clone())); - C.push((3, num_vars + 1, one)); - - let inst = Instance::::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap(); - - // compute a satisfying assignment - let mut rng = ark_std::rand::thread_rng(); - let z0 = E::ScalarField::rand(&mut rng); - let z1 = z0 * z0; // constraint 0 - let z2 = z1 * z0; // constraint 1 - let z3 = z2 + z0; // constraint 2 - let i0 = z3 + E::ScalarField::from(5u32); // constraint 3 - - // create a VarsAssignment - let mut vars = vec![E::ScalarField::zero().into_bigint().to_bytes_le(); num_vars]; - vars[0] = z0.into_bigint().to_bytes_le(); - vars[1] = z1.into_bigint().to_bytes_le(); - vars[2] = z2.into_bigint().to_bytes_le(); - vars[3] = z3.into_bigint().to_bytes_le(); - let assignment_vars = VarsAssignment::new(&vars).unwrap(); - - // create an InputsAssignment - let mut inputs = vec![E::ScalarField::zero().into_bigint().to_bytes_le(); num_inputs]; - inputs[0] = i0.into_bigint().to_bytes_le(); - let assignment_inputs = InputsAssignment::new(&inputs).unwrap(); - - // check if the instance we created is satisfiable - let res = inst.is_sat(&assignment_vars, &assignment_inputs); - assert!(res.unwrap(), "should be satisfied"); - - ( - num_cons, - num_vars, - num_inputs, - num_non_zero_entries, - inst, - assignment_vars, - assignment_inputs, - ) -} - -type E = ark_bls12_377::Bls12_377; -fn main() { - // produce an R1CS instance - let ( - num_cons, - num_vars, - num_inputs, - num_non_zero_entries, - inst, - assignment_vars, - assignment_inputs, - ) = produce_r1cs::(); - - let params = poseidon_params(); - - // produce public parameters - let gens = TestudoSnarkGens::::setup( - num_cons, - num_vars, - num_inputs, - num_non_zero_entries, - params.clone(), - ); - - // create a commitment to the R1CS instance - let (comm, decomm) = TestudoSnark::encode(&inst, &gens); - - // produce a proof of satisfiability - let mut prover_transcript = PoseidonTranscript::new(¶ms); - let proof = TestudoSnark::prove( - &inst, - &comm, - &decomm, - assignment_vars, - &assignment_inputs, - &gens, - &mut prover_transcript, - params.clone(), - ) - .unwrap(); - - // verify the proof of satisfiability - let mut verifier_transcript = PoseidonTranscript::new(¶ms); - assert!(proof - .verify( - &gens, - &comm, - &assignment_inputs, - &mut verifier_transcript, - params - ) - .is_ok()); - println!("proof verification successful!"); -} +// //! Demonstrates how to produces a proof for canonical cubic equation: `x^3 + x + 5 = y`. +// //! The example is described in detail [here]. +// //! +// //! The R1CS for this problem consists of the following 4 constraints: +// //! `Z0 * Z0 - Z1 = 0` +// //! `Z1 * Z0 - Z2 = 0` +// //! `(Z2 + Z0) * 1 - Z3 = 0` +// //! `(Z3 + 5) * 1 - I0 = 0` +// //! +// //! [here]: https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649 +// use ark_ec::pairing::Pairing; +// use ark_ff::{BigInteger, PrimeField}; +// use ark_std::{One, UniformRand, Zero}; +// use libtestudo::testudo_snark::{TestudoSnark, TestudoSnarkGens}; +// use libtestudo::{ +// parameters::poseidon_params, poseidon_transcript::PoseidonTranscript, InputsAssignment, Instance, +// VarsAssignment, +// }; + +// #[allow(non_snake_case)] +// fn produce_r1cs() -> ( +// usize, +// usize, +// usize, +// usize, +// Instance, +// VarsAssignment, +// InputsAssignment, +// ) { +// // parameters of the R1CS instance +// let num_cons = 4; +// let num_vars = 4; +// let num_inputs = 1; +// let num_non_zero_entries = 8; + +// // We will encode the above constraints into three matrices, where +// // the coefficients in the matrix are in the little-endian byte order +// let mut A: Vec<(usize, usize, Vec)> = Vec::new(); +// let mut B: Vec<(usize, usize, Vec)> = Vec::new(); +// let mut C: Vec<(usize, usize, Vec)> = Vec::new(); + +// let one = E::ScalarField::one().into_bigint().to_bytes_le(); + +// // R1CS is a set of three sparse matrices A B C, where is a row for every +// // constraint and a column for every entry in z = (vars, 1, inputs) +// // An R1CS instance is satisfiable iff: +// // Az \circ Bz = Cz, where z = (vars, 1, inputs) + +// // constraint 0 entries in (A,B,C) +// // constraint 0 is Z0 * Z0 - Z1 = 0. +// A.push((0, 0, one.clone())); +// B.push((0, 0, one.clone())); +// C.push((0, 1, one.clone())); + +// // constraint 1 entries in (A,B,C) +// // constraint 1 is Z1 * Z0 - Z2 = 0. +// A.push((1, 1, one.clone())); +// B.push((1, 0, one.clone())); +// C.push((1, 2, one.clone())); + +// // constraint 2 entries in (A,B,C) +// // constraint 2 is (Z2 + Z0) * 1 - Z3 = 0. +// A.push((2, 2, one.clone())); +// A.push((2, 0, one.clone())); +// B.push((2, num_vars, one.clone())); +// C.push((2, 3, one.clone())); + +// // constraint 3 entries in (A,B,C) +// // constraint 3 is (Z3 + 5) * 1 - I0 = 0. +// A.push((3, 3, one.clone())); +// A.push(( +// 3, +// num_vars, +// E::ScalarField::from(5u32).into_bigint().to_bytes_le(), +// )); +// B.push((3, num_vars, one.clone())); +// C.push((3, num_vars + 1, one)); + +// let inst = Instance::::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap(); + +// // compute a satisfying assignment +// let mut rng = ark_std::rand::thread_rng(); +// let z0 = E::ScalarField::rand(&mut rng); +// let z1 = z0 * z0; // constraint 0 +// let z2 = z1 * z0; // constraint 1 +// let z3 = z2 + z0; // constraint 2 +// let i0 = z3 + E::ScalarField::from(5u32); // constraint 3 + +// // create a VarsAssignment +// let mut vars = vec![E::ScalarField::zero().into_bigint().to_bytes_le(); num_vars]; +// vars[0] = z0.into_bigint().to_bytes_le(); +// vars[1] = z1.into_bigint().to_bytes_le(); +// vars[2] = z2.into_bigint().to_bytes_le(); +// vars[3] = z3.into_bigint().to_bytes_le(); +// let assignment_vars = VarsAssignment::new(&vars).unwrap(); + +// // create an InputsAssignment +// let mut inputs = vec![E::ScalarField::zero().into_bigint().to_bytes_le(); num_inputs]; +// inputs[0] = i0.into_bigint().to_bytes_le(); +// let assignment_inputs = InputsAssignment::new(&inputs).unwrap(); + +// // check if the instance we created is satisfiable +// let res = inst.is_sat(&assignment_vars, &assignment_inputs); +// assert!(res.unwrap(), "should be satisfied"); + +// ( +// num_cons, +// num_vars, +// num_inputs, +// num_non_zero_entries, +// inst, +// assignment_vars, +// assignment_inputs, +// ) +// } + +// type E = ark_bls12_377::Bls12_377; +// fn main() { +// // produce an R1CS instance +// let ( +// num_cons, +// num_vars, +// num_inputs, +// num_non_zero_entries, +// inst, +// assignment_vars, +// assignment_inputs, +// ) = produce_r1cs::(); + +// let params = poseidon_params(); + +// // produce public parameters +// let gens = TestudoSnarkGens::::setup( +// num_cons, +// num_vars, +// num_inputs, +// num_non_zero_entries, +// params.clone(), +// ); + +// // create a commitment to the R1CS instance +// let (comm, decomm) = TestudoSnark::encode(&inst, &gens); + +// // produce a proof of satisfiability +// let mut prover_transcript = PoseidonTranscript::new(¶ms); +// let proof = TestudoSnark::prove( +// &inst, +// &comm, +// &decomm, +// assignment_vars, +// &assignment_inputs, +// &gens, +// &mut prover_transcript, +// params.clone(), +// ) +// .unwrap(); + +// // verify the proof of satisfiability +// let mut verifier_transcript = PoseidonTranscript::new(¶ms); +// assert!(proof +// .verify( +// &gens, +// &comm, +// &assignment_inputs, +// &mut verifier_transcript, +// params +// ) +// .is_ok()); +// println!("proof verification successful!"); +// } + +fn main() {} diff --git a/profiler/testudo.rs b/profiler/testudo.rs index 92f7c267..f97fd93c 100644 --- a/profiler/testudo.rs +++ b/profiler/testudo.rs @@ -1,92 +1,94 @@ -#![allow(non_snake_case)] -#![allow(clippy::assertions_on_result_states)] +// #![allow(non_snake_case)] +// #![allow(clippy::assertions_on_result_states)] -extern crate libtestudo; -extern crate merlin; -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use ark_ec::pairing::Pairing; -use ark_ff::PrimeField; -use ark_serialize::*; -use libtestudo::parameters::PoseidonConfiguration; -use libtestudo::poseidon_transcript::PoseidonTranscript; -use libtestudo::{ - testudo_snark::{TestudoSnark, TestudoSnarkGens}, - Instance, -}; +// extern crate libtestudo; +// extern crate merlin; +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; +// use ark_ff::PrimeField; +// use ark_serialize::*; +// use libtestudo::parameters::PoseidonConfiguration; +// use libtestudo::poseidon_transcript::PoseidonTranscript; +// use libtestudo::{ +// testudo_snark::{TestudoSnark, TestudoSnarkGens}, +// Instance, +// }; -fn print(msg: &str) { - let star = "* "; - println!("{:indent$}{}{}", "", star, msg, indent = 2); -} +// fn print(msg: &str) { +// let star = "* "; +// println!("{:indent$}{}{}", "", star, msg, indent = 2); +// } -fn main() { - let params = ark_bls12_377::Fr::poseidon_params(); - profiler::(params); -} +// fn main() { +// let params = ark_bls12_377::Fr::poseidon_params(); +// profiler::(params); +// } -fn profiler(params: PoseidonConfig) -where - E: Pairing, - E::ScalarField: PrimeField, - E::ScalarField: Absorb, -{ - // the list of number of variables (and constraints) in an R1CS instance - let inst_sizes = vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; +// fn profiler(params: PoseidonConfig) +// where +// E: Pairing, +// E::ScalarField: PrimeField, +// E::ScalarField: Absorb, +// { +// // the list of number of variables (and constraints) in an R1CS instance +// let inst_sizes = vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; - println!("Profiler:: SNARK"); - for &s in inst_sizes.iter() { - let num_vars = (2_usize).pow(s as u32); - let num_cons = num_vars; - let num_inputs = 10; +// println!("Profiler:: SNARK"); +// for &s in inst_sizes.iter() { +// let num_vars = (2_usize).pow(s as u32); +// let num_cons = num_vars; +// let num_inputs = 10; - // produce a synthetic R1CSInstance - let (inst, vars, inputs) = - Instance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); +// // produce a synthetic R1CSInstance +// let (inst, vars, inputs) = +// Instance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - // produce public generators - let gens = - TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, params.clone()); +// // produce public generators +// let gens = +// TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, params.clone()); - // create a commitment to R1CSInstance - let (comm, decomm) = TestudoSnark::encode(&inst, &gens); +// // create a commitment to R1CSInstance +// let (comm, decomm) = TestudoSnark::encode(&inst, &gens); - // produce a proof of satisfiability - let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); - let proof = TestudoSnark::prove( - &inst, - &comm, - &decomm, - vars, - &inputs, - &gens, - &mut prover_transcript, - params.clone(), - ) - .unwrap(); +// // produce a proof of satisfiability +// let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); +// let proof = TestudoSnark::prove( +// &inst, +// &comm, +// &decomm, +// vars, +// &inputs, +// &gens, +// &mut prover_transcript, +// params.clone(), +// ) +// .unwrap(); - let mut proof_encoded = Vec::new(); - proof - .serialize_with_mode(&mut proof_encoded, Compress::Yes) - .unwrap(); - let msg_proof_len = format!( - "TestudoSnark::proof_compressed_len {:?}", - proof_encoded.len() - ); - print(&msg_proof_len); +// let mut proof_encoded = Vec::new(); +// proof +// .serialize_with_mode(&mut proof_encoded, Compress::Yes) +// .unwrap(); +// let msg_proof_len = format!( +// "TestudoSnark::proof_compressed_len {:?}", +// proof_encoded.len() +// ); +// print(&msg_proof_len); - // verify the proof of satisfiability - let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); - assert!(proof - .verify( - &gens, - &comm, - &inputs, - &mut verifier_transcript, - params.clone() - ) - .is_ok()); +// // verify the proof of satisfiability +// let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); +// assert!(proof +// .verify( +// &gens, +// &comm, +// &inputs, +// &mut verifier_transcript, +// params.clone() +// ) +// .is_ok()); - println!(); - } -} +// println!(); +// } +// } + +fn main() {} diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index 3d48f1e1..dbc1a21a 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -16,6 +16,7 @@ use ark_crypto_primitives::sponge::{ use ark_crypto_primitives::Error; use ark_ec::pairing::Pairing; use ark_ec::AffineRepr; +use ark_ec::CurveGroup; use ark_ff::BigInteger; use ark_ff::PrimeField; use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; @@ -24,6 +25,7 @@ use ark_poly_commit::multilinear_pc::{ data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, MultilinearPC, }; +use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; use ark_r1cs_std::groups::bls12::G1Var; use ark_r1cs_std::prelude::*; use ark_r1cs_std::{ @@ -84,20 +86,20 @@ pub struct CommitmentG2Var> { pub h_product: IV::G2Var, } -struct TestudoCommVerifier +pub struct TestudoCommVerifier where E: Pairing, IV: PairingVar, { - //transcript: PoseidonTranscript, - vk: VerifierKey, - U: Commitment, - point: Vec, - v: E::ScalarField, - pst_proof: Proof, - mipp_proof: MippProof, - T: E::TargetField, - _iv: PhantomData, + pub state: E::ScalarField, + pub vk: VerifierKey, + pub U: Commitment, + pub point: Vec, + pub v: E::ScalarField, + pub pst_proof: Proof, + pub mipp_proof: MippProof, + pub T: E::TargetField, + pub _iv: PhantomData, } impl Clone for TestudoCommVerifier where @@ -106,7 +108,7 @@ where { fn clone(&self) -> Self { Self { - // transcript: self.transcript.clone(), + state: self.state.clone(), vk: self.vk.clone(), U: self.U.clone(), point: self.point.clone(), @@ -126,7 +128,7 @@ where IV::G1Var: CurveVar, IV::G2Var: CurveVar, IV::GTVar: FieldVar, - IV::G1Var: AbsorbGadget, + //IV::G1Var: AbsorbGadget, // IV::GTVar: AbsorbGadget, //>::GTVar: AbsorbGadget<::BaseField> { @@ -135,42 +137,59 @@ where cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { // allocate point - let mut point_var = Vec::new(); - for p in self.point.clone().into_iter() { - let scalar_in_fq = &E::BaseField::from_bigint( - ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), - ) - .unwrap(); - let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - point_var.push(p_var); + let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); + let state_var = + NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.state)) + .unwrap(); + + println!("STATE VAR {:?}", state_var.value().unwrap()); + + let mut x_var_vec: Vec> = Vec::new(); + for x in state_var.to_bytes()?.value().unwrap() { + x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); } - let len = point_var.len(); - let odd = if len % 2 == 1 { 1 } else { 0 }; - let a_var = &point_var[0..len / 2 + odd]; - let b_var = &point_var[len / 2 + odd..len]; - - let res_mipp = mipp_verify_gadget::( - cs.clone(), - self.vk.clone(), - &self.mipp_proof, - b_var.to_vec(), - self.U.g_product, - &self.T, - ); - - assert!(res_mipp.unwrap() == true); - let mut a_rev_var = a_var.to_vec().clone(); - a_rev_var.reverse(); - - let res_var = check_gadget::( - cs.clone(), - self.vk, - self.U, - &a_rev_var, - self.v, - self.pst_proof, - ); - assert!(res_var.unwrap() == true); + constraint_sponge.absorb(&x_var_vec).unwrap(); + + let (hash_var1, hash_var2) = constraint_sponge + .squeeze_nonnative_field_elements::(1) + .unwrap(); + println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); + // let mut point_var = Vec::new(); + // for p in self.point.clone().into_iter() { + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + // let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // point_var.push(p_var); + // } + // let len = point_var.len(); + // let odd = if len % 2 == 1 { 1 } else { 0 }; + // let a_var = &point_var[0..len / 2 + odd]; + // let b_var = &point_var[len / 2 + odd..len]; + + // let res_mipp = mipp_verify_gadget::( + // cs.clone(), + // self.vk.clone(), + // &self.mipp_proof, + // b_var.to_vec(), + // self.U.g_product, + // &self.T, + // ); + + // assert!(res_mipp.unwrap() == true); + // let mut a_rev_var = a_var.to_vec().clone(); + // a_rev_var.reverse(); + + // let res_var = check_gadget::( + // cs.clone(), + // self.vk, + // self.U, + // &a_rev_var, + // self.v, + // self.pst_proof, + // ); + // assert!(res_var.unwrap() == true); Ok(()) } } @@ -599,20 +618,20 @@ mod tests { let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let circuit = TestudoCommVerifier { - vk, - U: u, - point: r, - v, - pst_proof, - mipp_proof, - T: t, - _iv: PhantomData::, - }; - - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - circuit.generate_constraints(cs.clone()).unwrap(); - assert!(cs.is_satisfied().unwrap()); + // let circuit = TestudoCommVerifier { + // vk, + // U: u, + // point: r, + // v, + // pst_proof, + // mipp_proof, + // T: t, + // _iv: PhantomData::, + // }; + + // let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + // circuit.generate_constraints(cs.clone()).unwrap(); + // assert!(cs.is_satisfied().unwrap()); // let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); // let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); diff --git a/src/constraints.rs b/src/constraints.rs index c91a9a37..14ad65b9 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,42 +1,24 @@ -use crate::ark_std::One; -use crate::mipp::MippProof; -use crate::parameters::get_bls12377_fq_params; -use crate::parameters::params_to_base_field; +use std::borrow::Borrow; +use ark_ec::pairing::Pairing; use crate::{ math::Math, - poseidon_transcript::PoseidonTranscript, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, }; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; + +use ark_ff::PrimeField; + use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; -use ark_crypto_primitives::Error; -use ark_ec::pairing::Pairing; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; -use ark_poly_commit::multilinear_pc::data_structures::ProofG1; -use ark_poly_commit::multilinear_pc::{ - data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, - MultilinearPC, -}; -use ark_r1cs_std::groups::bls12::G1Var; -use ark_r1cs_std::prelude::*; +use ark_poly_commit::multilinear_pc::data_structures::Commitment; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, fields::fp::FpVar, prelude::{EqGadget, FieldVar}, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; -use ark_serialize::Compress; -use digest::generic_array::typenum::True; -use std::ops::AddAssign; -use std::ops::Mul; -use std::ops::MulAssign; -use std::{borrow::Borrow, marker::PhantomData}; pub struct PoseidonTranscripVar where @@ -493,536 +475,4 @@ pub struct VerifierConfig { // .enforce_equal(&Boolean::constant(true))?; // Ok(()) // } -// } -// struct MippTUVar -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, -// IV::GTVar: FieldVar, -// { -// pub tc: IV::GTVar, -// pub uc: IV::G1Var, -// } - -// impl Default for MippTUVar -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, -// IV::GTVar: FieldVar, -// { -// fn default() -> Self { -// Self { -// tc: IV::GTVar::one(), -// uc: IV::G1Var::zero(), -// } -// } -// } -// impl MippTUVar -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, -// IV::GTVar: FieldVar, -// { -// fn merge(&mut self, other: &Self) { -// self.tc.mul_assign(&other.tc); -// self.uc.add_assign(&other.uc); -// } -// } -// pub struct CommitmentG2Var> { -// /// number of variables -// pub nv: usize, -// /// product of g as described by the vRAM paper -// pub h_product: IV::G2Var, -// } - -// struct TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// { -// //transcript: PoseidonTranscript, -// vk: VerifierKey, -// U: Commitment, -// point: Vec, -// v: E::ScalarField, -// pst_proof: Proof, -// mipp_proof: MippProof, -// T: E::TargetField, -// _iv: PhantomData, -// } -// impl Clone for TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// { -// fn clone(&self) -> Self { -// Self { -// // transcript: self.transcript.clone(), -// vk: self.vk.clone(), -// U: self.U.clone(), -// point: self.point.clone(), -// v: self.v.clone(), -// pst_proof: self.pst_proof.clone(), -// mipp_proof: self.mipp_proof.clone(), -// T: self.T.clone(), -// _iv: self._iv, -// } -// } -// } - -// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, -// IV::G2Var: CurveVar, -// IV::GTVar: FieldVar, -// IV::G1Var: AbsorbGadget, -// // IV::GTVar: AbsorbGadget, -// //>::GTVar: AbsorbGadget<::BaseField> -// { -// fn generate_constraints( -// self, -// cs: ConstraintSystemRef<::BaseField>, -// ) -> Result<(), SynthesisError> { -// // allocate point -// let mut point_var = Vec::new(); -// for p in self.point.clone().into_iter() { -// let scalar_in_fq = &E::BaseField::from_bigint( -// ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), -// ) -// .unwrap(); -// let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; -// point_var.push(p_var); -// } -// let len = point_var.len(); -// let odd = if len % 2 == 1 { 1 } else { 0 }; -// let a_var = &point_var[0..len / 2 + odd]; -// let b_var = &point_var[len / 2 + odd..len]; - -// // start mipp verify -// // start allocate struct mipp proof -// // allocate comms_u -// let mut comms_u_var = Vec::new(); -// for (first, second) in self.mipp_proof.comms_u.clone().into_iter() { -// let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; -// let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; -// comms_u_var.push((first_var, second_var)); -// } -// // allocate comms_t -// let mut comms_t_var = Vec::new(); -// for (first, second) in self.mipp_proof.comms_t.clone().into_iter() { -// let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; -// let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; -// comms_t_var.push((first_var, second_var)); -// } - -// let mut xs = Vec::new(); -// let mut xs_inv = Vec::new(); -// let mut final_y = E::BaseField::one(); -// let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(final_y))?; - -// // start allocate T -// let T_var = IV::GTVar::new_input(cs.clone(), || Ok(self.T))?; -// // start allocate U.g_product -// let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(self.U.g_product))?; - -// let mut final_res_var: MippTUVar = MippTUVar { -// tc: T_var.clone(), -// uc: U_g_product_var.clone(), -// }; - -// let params: PoseidonConfig = params_to_base_field::(); -// let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); -// transcript_var.absorb(&U_g_product_var); - -// for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { -// let (comm_u_l, comm_u_r) = comm_u; -// let (comm_t_l, comm_t_r) = comm_t; -// // Fiat-Shamir challenge - -// transcript_var.absorb(comm_u_l); -// transcript_var.absorb(comm_u_r); -// // ATTENTION -// let comm_t_l_bit = comm_t_l.to_bytes()?; -// transcript_var.absorb(&comm_t_l_bit); -// let comm_t_r_bit = comm_t_r.to_bytes()?; -// transcript_var.absorb(&comm_t_r_bit); -// // transcript_var.absorb(comm_t_r); -// let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); -// let c_var = c_inv_var.inverse().unwrap(); - -// xs.push(c_var.clone()); -// xs_inv.push(c_inv_var.clone()); - -// let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; -// final_y_var *= one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; -// } - -// enum Op<'a, E: Pairing, IV: PairingVar> { -// TC(&'a IV::GTVar, FpVar<::BaseField>), -// UC(&'a IV::G1Var, &'a FpVar<::BaseField>), -// } - -// let res_var = comms_t_var -// .iter() -// .zip(comms_u_var.iter()) -// .zip(xs.iter().zip(xs_inv.iter())) -// .flat_map(|((comm_t, comm_u), (c, c_inv))| { -// let (comm_t_l, comm_t_r) = comm_t; -// let (comm_u_l, comm_u_r) = comm_u; - -// // we multiple left side by x^-1 and right side by x -// vec![ -// Op::TC(comm_t_l, c_inv.clone()), -// Op::TC(comm_t_r, c.clone()), -// Op::UC(comm_u_l, c_inv), -// Op::UC(comm_u_r, c), -// ] -// }) -// .fold(MippTUVar::::default(), |mut res, op: Op| { -// match op { -// Op::TC(tx, c) => { -// // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; -// let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); -// res.tc.mul_assign(&tx); -// } -// Op::UC(zx, c) => { -// let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); -// res.uc.add_assign(&uxp); -// } -// } -// res -// }); - -// let ref_final_res_var = &mut final_res_var; -// ref_final_res_var.merge(&res_var); - -// let mut rs: Vec::BaseField>> = Vec::new(); -// let m = xs_inv.len(); -// for _i in 0..m { -// let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); -// rs.push(r); -// } - -// let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; - -// // let rs_var = rs.clone(); -// let v_var: FpVar<::BaseField> = (0..m) -// .into_iter() -// .map(|i| one_var.clone() + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) -// .fold(one_var.clone(), |acc, x| acc * x); - -// let comm_h = CommitmentG2:: { -// nv: m, -// h_product: self.mipp_proof.final_h, -// }; - -// let check_h = check_2_gadget::( -// cs.clone(), -// self.vk.clone(), -// &comm_h, -// &rs, -// v_var, -// &self.mipp_proof.pst_proof_h, -// ); -// assert!(check_h == true); - -// let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_a))?; -// let final_u_var = final_a_var -// .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) -// .unwrap(); - -// let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(self.mipp_proof.final_h))?; - -// let final_u_var_prep = IV::prepare_g1(&final_a_var).unwrap(); -// let final_h_var_prep = IV::prepare_g2(&final_h_var).unwrap(); - -// let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep).unwrap(); -// let check_t; - -// if () == ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap() { -// check_t = true; -// } else { -// check_t = false; -// } -// assert!(check_t == true); - -// let check_u; -// if () == ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { -// check_u = true; -// } else { -// check_u = false; -// } -// assert!(check_u == true); - -// let mut a_rev_var = a_var.to_vec().clone(); -// a_rev_var.reverse(); - -// // MAKE PST CHECKKK -// let res_var = check_gadget::( -// cs.clone(), -// self.vk, -// self.U, -// &a_rev_var, -// self.v, -// self.pst_proof, -// ); -// assert!(res_var.unwrap() == true); -// Ok(()) -// } -// } - -// fn check_2_gadget>( -// cs: ConstraintSystemRef, -// vk: VerifierKey, -// commitment: &CommitmentG2, -// point_var: &Vec::BaseField>>, -// value_var: FpVar<::BaseField>, -// proof: &ProofG1, -// ) -> bool -// where -// IV::G1Var: CurveVar, -// IV::G2Var: CurveVar, -// IV::GTVar: FieldVar, -// { -// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g)).unwrap(); -// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h)).unwrap(); -// let mut vk_gmask_var = Vec::new(); -// for g_mask in vk.g_mask_random.clone().into_iter() { -// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask)).unwrap(); -// vk_gmask_var.push(g_mask_var); -// } -// // allocate commitment -// let com_g2_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product)).unwrap(); - -// let pair_right_op = com_g2_prod_var -// - (vk_h_var -// .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) -// .unwrap()); -// let right_prepared = IV::prepare_g2(&pair_right_op).unwrap(); -// let left_prepared = IV::prepare_g1(&vk_g_var).unwrap(); -// let left = IV::pairing(left_prepared, right_prepared).unwrap(); - -// let mut h_mul_var = Vec::new(); - -// for p in point_var.into_iter() { -// let x = vk_h_var -// .scalar_mul_le(p.to_bits_le().unwrap().iter()) -// .unwrap(); -// h_mul_var.push(x); -// } -// let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); -// let mut h_mask_random_var = Vec::new(); -// for h_mask in h_mask_random.clone().into_iter() { -// let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask)).unwrap(); -// h_mask_random_var.push(h_mask_var); -// } -// let pairing_rights_var: Vec<_> = (0..vk.nv) -// .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) -// .collect(); -// let pairing_rights_var: Vec = pairing_rights_var -// .into_iter() -// .map(|p| IV::prepare_g2(&p).unwrap()) -// .collect(); -// let mut proofs_var = Vec::new(); -// for p in proof.proofs.clone().into_iter() { -// let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p)).unwrap(); -// proofs_var.push(proof_var); -// } -// let pairing_lefts_var: Vec = proofs_var -// .into_iter() -// .map(|p| IV::prepare_g1(&p).unwrap()) -// .collect(); - -// let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var).unwrap(); -// let right = IV::final_exponentiation(&right_ml).unwrap(); - -// if () == left.enforce_equal(&right).unwrap() { -// true -// } else { -// false -// } -// } - -// fn check_gadget>( -// cs: ConstraintSystemRef, -// vk: VerifierKey, -// commitment: Commitment, -// point_var: &Vec::BaseField>>, -// value: E::ScalarField, -// proof: Proof, -// ) -> Result -// where -// IV::G1Var: CurveVar, -// IV::G2Var: CurveVar, -// IV::GTVar: FieldVar, -// { -// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; -// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; -// let mut vk_gmask_var = Vec::new(); -// for g_mask in vk.g_mask_random.clone().into_iter() { -// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; -// vk_gmask_var.push(g_mask_var); -// } -// // allocate commitment -// let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; -// // allocate value -// let scalar_in_fq = &E::BaseField::from_bigint( -// ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), -// ) -// .unwrap(); -// let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; -// // allocate proof -// let mut proofs_var = Vec::new(); -// for proof in proof.proofs.clone().into_iter() { -// let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; -// proofs_var.push(proof_var); -// } -// // start operation on circuit -// let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); -// let left_prepared = IV::prepare_g1(&pair_left_op)?; -// let right_prepared = IV::prepare_g2(&vk_h_var)?; -// let left = IV::pairing(left_prepared, right_prepared)?; - -// //calculating msm with framework function outside the circuit -// // let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize; -// // let window_size = FixedBase::get_mul_window_size(self.vk.nv); - -// // let g_table = FixedBase::get_window_table(scalar_size, window_size, self.vk.g.into_group()); -// // let g_mul: Vec = -// // FixedBase::msm(scalar_size, window_size, &g_table, self.point.as_slice()); - -// //calculate basic msm -// // let mut res = Vec::new(); -// // for s in point.into_iter() { -// // res.push(vk.g.mul(s)); -// // } - -// //check basic msm with basic vector -// //assert_eq!(res, g_mul); - -// let mut res_var = Vec::new(); - -// for p in point_var.into_iter() { -// let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; -// res_var.push(x); -// } - -// //do msm with circuit variable -// // let mut g_mul_var = Vec::new(); -// // for g_m in g_mul.clone().into_iter() { -// // let g_m_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_m))?; -// // g_mul_var.push(g_m_var); -// // } - -// //assert vector calculated with msm and allocated is equal to msm calculated locally with variable -// //res_var.enforce_equal(&g_mul_var)?; - -// //computing other part of the circuit -// let pairing_lefts_var: Vec<_> = (0..vk.nv) -// .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) -// .collect(); - -// let mut pairing_lefts_prep = Vec::new(); -// for var in pairing_lefts_var.clone().into_iter() { -// pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); -// } - -// let mut pairing_right_prep = Vec::new(); -// for var in proofs_var.clone().into_iter() { -// pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); -// } - -// let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; -// let right = IV::final_exponentiation(&right_ml).unwrap(); -// if () == left.enforce_equal(&right).unwrap() { -// Ok(true) -// } else { -// Ok(false) -// } -// } - -// #[cfg(test)] -// mod tests { -// use crate::ark_std::UniformRand; -// use ark_bls12_377::{Bls12_377, Config, FqConfig}; -// use ark_bls12_381::Bls12_381; -// use ark_ec::pairing::Pairing; -// use ark_ec::short_weierstrass::Affine; -// use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; -// use ark_std::rand::RngCore; -// use ark_std::test_rng; -// use ark_std::vec::Vec; -// type E = Bls12_377; -// use ark_relations::r1cs::ConstraintSystem; -// type Fr = ::ScalarField; -// use super::*; -// use ark_ec::bls12::Bls12; -// type IV = ark_bls12_377::constraints::PairingVar; -// use crate::ark_std::rand::SeedableRng; -// use ark_bw6_761::BW6_761 as P; -// use ark_crypto_primitives::snark::SNARK; -// use ark_ff::Field; -// use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; -// use ark_groth16::prepare_verifying_key; -// use ark_groth16::Groth16; -// type Fp = ::BaseField; -// use super::*; -// type F = ark_bls12_377::Fr; -// use crate::parameters::poseidon_params; -// use crate::sqrt_pst::Polynomial; - -// #[test] -// fn check_commit() { -// // check odd case -// check_sqrt_poly_commit(5); -// } - -// fn check_sqrt_poly_commit(num_vars: u32) { -// let mut rng = ark_std::test_rng(); -// let len = 2_usize.pow(num_vars); -// let Z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); -// let r: Vec = (0..num_vars) -// .into_iter() -// .map(|_| F::rand(&mut rng)) -// .collect(); - -// let gens = MultilinearPC::::setup(3, &mut rng); -// let (ck, vk) = MultilinearPC::::trim(&gens, 3); - -// let mut pl = Polynomial::from_evaluations(&Z.clone()); - -// let v = pl.eval(&r); - -// let (comm_list, t) = pl.commit(&ck); - -// let params = poseidon_params(); -// let mut prover_transcript = PoseidonTranscript::new(¶ms); - -// let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - -// let mut verifier_transcript = PoseidonTranscript::new(¶ms); - -// let circuit = TestudoCommVerifier { -// vk, -// U: u, -// point: r, -// v, -// pst_proof, -// mipp_proof, -// T: t, -// _iv: PhantomData::, -// }; - -// let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); -// let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); -// let opvk = Groth16::

::process_vk(&ovk).unwrap(); -// let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); -// let public_input = vec![]; -// assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); -// } -// } +// } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 15de3687..f0fe6222 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,10 +21,17 @@ mod dense_mlpoly; mod errors; #[macro_use] pub(crate) mod macros; +mod circuit_verifier; +mod constraints; mod math; pub(crate) mod mipp; mod nizk; +pub mod parameters; +pub mod poseidon_transcript; mod product_tree; +mod prova; +mod prova2; +mod prova3; mod r1csinstance; mod r1csproof; mod sparse_mlpoly; @@ -35,13 +42,7 @@ pub mod testudo_snark; mod timer; pub(crate) mod transcript; mod unipoly; - -mod circuit_verifier; -mod constraints; -pub mod parameters; -pub mod poseidon_transcript; -mod prova; -mod prova2; +mod verifier_circuit; use core::cmp::max; use errors::R1CSError; diff --git a/src/mipp.rs b/src/mipp.rs index 54b42a00..22ed3249 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -129,6 +129,7 @@ impl MippProof { xs_inv.len(), Self::polynomial_evaluations_from_transcript::(&xs_inv), ); + let c = MultilinearPC::::commit_g2(ck, &poly); debug_assert!(c.h_product == final_h); @@ -139,8 +140,7 @@ impl MippProof { .map(|_| transcript.challenge_scalar::(b"random_point")) .collect(); - println!("Prover"); - println!("{}", rs[0]); + println!("RS PROVER {:?}", rs); let pst_proof_h = MultilinearPC::::open_g1(ck, &poly, &rs); Ok(MippProof { @@ -213,9 +213,6 @@ impl MippProof { transcript.append(b"comm_t_l", comm_t_l); transcript.append(b"comm_t_r", comm_t_r); let c_inv = transcript.challenge_scalar::(b"challenge_i"); - println!("PRIMA SQUEEZY NAIVE"); - println!("{}", c_inv); - break; let c = c_inv.inverse().unwrap(); xs.push(c); @@ -283,8 +280,6 @@ impl MippProof { rs.push(r); } - println!("Verifier 1"); - println!("{}", rs[0]); // Given p_h is structured as defined above, the verifier can compute // p_h(rs) by themselves in O(m) time let v = (0..m) @@ -292,13 +287,13 @@ impl MippProof { .map(|i| E::ScalarField::one() + rs[i].mul(xs_inv[m - i - 1]) - rs[i]) .product(); - println!("Verifier 2"); - println!("{}", rs[0]); let comm_h = CommitmentG2 { nv: m, h_product: proof.final_h, }; + println!("RS VERIFIER {:?}",rs); + // final_h is the commitment of p_h so the verifier can perform // a PST verification at the random point rs, given the pst proof // received from the prover prover diff --git a/src/parameters.rs b/src/parameters.rs index 6928a84b..785e7ead 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -275,6 +275,37 @@ where 1, ) } +pub fn get_bw6_fr_params() -> PoseidonConfig { + let arks = FR["ark"] + .members() + .map(|ark| { + ark + .members() + .map(|v| ark_bw6_761::Fr::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); + let mds = FR["mds"] + .members() + .map(|m| { + m.members() + .map(|v| ark_bw6_761::Fr::from_str(v.as_str().unwrap()).unwrap()) + .collect::>() + }) + .collect::>(); + PoseidonConfig::new( + FR["full_rounds"].as_usize().unwrap(), + FR["partial_rounds"].as_usize().unwrap(), + FR["alpha"].as_u64().unwrap(), + mds, + arks, + FR["rate"].as_usize().unwrap(), + // TODO (nikkolasg): check out the concrete parameters for the capacity + // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 + 1, + ) +} + pub fn get_bls12377_fq_params() -> PoseidonConfig { let arks = FR["ark"] .members() diff --git a/src/prova.rs b/src/prova.rs index bc7c7dd1..528cae2e 100644 --- a/src/prova.rs +++ b/src/prova.rs @@ -7,28 +7,25 @@ use ark_crypto_primitives::sponge::{ }; use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; use ark_ec::pairing::Pairing; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; use ark_r1cs_std::prelude::*; -use ark_r1cs_std::{ - alloc::AllocVar, - fields::fp::FpVar, - prelude::EqGadget, -}; +use ark_r1cs_std::ToConstraintFieldGadget; +use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; +use poseidon_parameters::PoseidonParameters; use std::marker::PhantomData; - struct TestudoCommVerifier where E: Pairing, IV: PairingVar, { - native_sponge: PoseidonTranscript, - constraint_sponge: PoseidonSpongeVar, - point: E::G1Affine, - scalar_in_fq: E::BaseField, - hash: E::BaseField, + scalar: E::ScalarField, + poseidon_params: PoseidonConfig, _iv: PhantomData, } @@ -37,75 +34,95 @@ where E: Pairing, IV: PairingVar, IV::G1Var: CurveVar, - >::G1Var: AbsorbGadget<::BaseField>, { fn generate_constraints( mut self, cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { - - - let params: PoseidonConfig = params_to_base_field::(); - - let mut buf = Vec::new(); - self.point - .serialize_with_mode(&mut buf, Compress::No) - .expect("serialization failed"); - - let mut sponge_naive = PoseidonSponge::::new(¶ms); - - let mut sponge_var = PoseidonSpongeVar::::new(cs.clone(),¶ms); - - sponge_naive.absorb(&buf); - - let real_hash: E::BaseField = sponge_naive.squeeze_field_elements(1).remove(0); - - println!("REAL HASH "); - println!("{}", real_hash); - - - let real_hash_var = FpVar::new_input(cs.clone(), || Ok(real_hash)).unwrap(); - - println!("REAL HASH VAR"); - println!("{}", real_hash_var.value().unwrap()); - - let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); - - //start allocation for absorb - let mut buf2 = Vec::new(); - point_var_affine.value().unwrap() - .serialize_with_mode(&mut buf2, Compress::No) - .expect("serialization failed"); - - let mut x_var_vec = Vec::new(); - - for x in buf2 { - x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - } - //end allocation for absorb - - println!(); - println!("STAMPO BYTE DI VARIABILI"); - for v in x_var_vec.clone() { - print!("{} - ", v.value()?); - } - println!(); - - - sponge_var - .absorb(&x_var_vec) - .unwrap(); - - - let hash_var = sponge_var - .squeeze_field_elements(1) - .unwrap() - .remove(0); - - println!("HASH_VAR: "); - println!("{}", hash_var.value().unwrap()); - - hash_var.enforce_equal(&real_hash_var).unwrap(); + // let hash_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); + + // println!("REAL HASH VAR"); + // println!("{:?}", real_hash_var.value().unwrap()); + + // // let scalar_in_fq = &E::BaseField::from_bigint( + // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // // ) + // // .unwrap(); + + // let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.scalar))?; + + // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // // println!("SCALAR VAR"); + // // println!("{:?}", scalar_var.value().unwrap()); + + // // let mut buf3 = Vec::new(); + // // scalar_var.value().unwrap() + // // .serialize_with_mode(&mut buf3, Compress::Yes) + // // .expect("serialization failed"); + + // // println!("SCALAR VAR BYTES"); + // // println!("{:?}", buf3); + + // self.constraint_sponge + // .absorb(&scalar_var.to_bytes()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = self.constraint_sponge + // .squeeze_nonnative_field_elements::(1) + // .unwrap(); + + // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); + // println!("HASH_VAR 1: "); + // println!("{:?}", hash_var1.value().unwrap()); + + // // for i in hash_var2 { + // // println!("{:?}", i.value().unwrap()); + // // } + // // println!("HASH_VAR 2: "); + // // println!("{:?}", hash_var2); + // real_hash_var.enforce_equal(&hash_var1[0]); + + // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); + // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); + + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + + // println!("STATE VAR {:?}", state_var.value().unwrap()); + + // let mut x_var_vec: Vec> = Vec::new(); + // for x in state_var.to_bytes()?.value().unwrap() { + // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + // } + // constraint_sponge + // .absorb(&scalar_in_fq()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = constraint_sponge + // .squeeze_nonnative_field_elements::(1).unwrap().pop() + // .unwrap(); + // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); + + let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); + let cv = NonNativeFieldVar::::new_witness(cs.clone(), || { + Ok(self.scalar.clone()) + })?; + println!("Scalar {:?}", cv.value().unwrap()); + println!("CF {:?}", cv.to_constraint_field()?.value().unwrap()); + sponge.absorb(&cv.to_constraint_field()?); + let hash = sponge.squeeze_nonnative_field_elements::(1)?; + + println!("hash {:?}", hash.0.value().unwrap()); + // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] Ok(()) } } @@ -114,6 +131,8 @@ where mod tests { use super::*; use crate::parameters::get_bls12377_fq_params; + use crate::parameters::get_bw6_fr_params; + use crate::parameters::poseidon_params; use crate::transcript::Transcript; use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; @@ -129,42 +148,41 @@ mod tests { let mut rng = test_rng(); let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - let sponge_params = get_bls12377_fq_params(); - - let mut native_sponge = PoseidonTranscript::new(&sponge_params); - let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); + let params = poseidon_params(); + let mut native_sponge = PoseidonTranscript::new(¶ms); let mut rng = ark_std::test_rng(); - let point = ark_bls12_377::G1Affine::rand(&mut rng); - let scalar = ark_bls12_377::Fr::rand(&mut rng); - let scalar_in_fq = - as Pairing>::BaseField::from_bigint(< as Pairing>::BaseField as PrimeField>::BigInt::from_bits_le( - scalar.into_bigint().to_bits_le().as_slice(), - )) - .unwrap(); - - - native_sponge.append(b"U", &point); - - let hash = native_sponge - .challenge_scalar::< as Pairing>::BaseField>(b"random_point"); + //let point = ark_bls12_377::G1Affine::rand(&mut rng); + let scalar = ark_bls12_377::Fr::from(5 as u8); + + println!("SCALAR "); + println!("{:?}", scalar); + + native_sponge.append(b"U", &scalar); + + let hash: ark_bls12_377::Fr = native_sponge.challenge_scalar(b"random_point"); println!("HASH: "); - println!("{}", hash); + println!("{:?}", hash); let circuit: TestudoCommVerifier = TestudoCommVerifier { - native_sponge, - constraint_sponge, - point, - scalar_in_fq, - hash, + scalar, + poseidon_params: get_bls12377_fq_params(), _iv: PhantomData, }; circuit.generate_constraints(cs.clone()).unwrap(); - ; assert!(cs.is_satisfied().unwrap()); + + let params = get_bls12377_fq_params(); + + let mut native_sponge2 = PoseidonTranscript::new(¶ms); + + native_sponge2.append(b"U", &scalar); + + let hash2: ark_bls12_377::Fr = native_sponge2.challenge_scalar(b"random_point"); + + println!("HASH2: "); + println!("{:?}", hash2); } -} \ No newline at end of file +} diff --git a/src/prova2.rs b/src/prova2.rs index 8f28ee84..e6571e2b 100644 --- a/src/prova2.rs +++ b/src/prova2.rs @@ -1,229 +1,197 @@ -use crate::ark_std::One; -use crate::ark_std::UniformRand; -use crate::mipp::MippProof; -use crate::parameters::get_bls12377_fq_params; -use crate::parameters::params_to_base_field; -use crate::{ - math::Math, - poseidon_transcript::PoseidonTranscript, - sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, - unipoly::UniPoly, -}; -use ark_bls12_377::g1::G1Affine; -use ark_bls12_377::Fr; -use ark_bls12_377::G1Projective; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::poseidon; -use ark_crypto_primitives::sponge::Absorb; -use ark_crypto_primitives::sponge::{ - constraints::CryptographicSpongeVar, - poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -}; -use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -use ark_crypto_primitives::Error; -use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; -use ark_ec::CurveGroup; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; -use ark_poly_commit::multilinear_pc::data_structures::ProofG1; -use ark_poly_commit::multilinear_pc::{ - data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, - MultilinearPC, -}; -use ark_r1cs_std::groups::bls12::G1Var; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::{ - alloc::{AllocVar, AllocationMode}, - fields::fp::FpVar, - prelude::{EqGadget, FieldVar}, -}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; -use ark_serialize::CanonicalSerialize; -use ark_serialize::Compress; -use digest::generic_array::typenum::True; -use std::ops::AddAssign; -use std::ops::Mul; -use std::ops::MulAssign; -use std::{borrow::Borrow, marker::PhantomData}; -struct TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - native_sponge: PoseidonTranscript, - constraint_sponge: PoseidonSpongeVar, - point: E::G1Affine, - scalar_in_fq: E::BaseField, - hash: E::BaseField, - _iv: PhantomData, -} - -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - >::G1Var: AbsorbGadget<::BaseField>, -{ - fn generate_constraints( - mut self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - let exp_hash_var = - FpVar::::new_witness(cs.clone(), || Ok(self.hash.clone())).unwrap(); - - println!("EXP_HASH_VAR: "); - println!("{}", exp_hash_var.value().unwrap()); - - let point_var_affine = IV::G1Var::new_input(cs.clone(), || Ok(self.point.clone())).unwrap(); - println!("POINT 2: "); - println!("{}", point_var_affine.value().unwrap()); - - // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(self.scalar_in_fq)).unwrap(); - - // println!("SCALAR_VAR: "); - // println!("{}", scalar_var.value().unwrap()); - // let x1 = point_var_affine.value().unwrap().into_affine().x().unwrap(); - // let y1 = point_var_affine.value().unwrap().into_affine().y().unwrap(); - // println!("X: "); - // println!("{}", x1); - // println!("Y: "); - // println!("{}", y1); - // let mut buf = Vec::new(); - // x1 - // .serialize_with_mode(&mut buf, Compress::No) - // .expect("serialization failed"); - - // println!("STAMPO VEC BYTE X1"); - // for v in buf.clone() { - // print!("{} - ", v); - // } - - // println!(""); - - // let mut buf2 = Vec::new(); - // y1 - // .serialize_with_mode(&mut buf2, Compress::No) - // .expect("serialization failed"); - - println!("STAMPO VEC BYTE"); - let prova = &point_var_affine.to_bytes().unwrap(); - for v in prova.clone() { - print!("{} - ", v.value().unwrap()); - } - - // println!("ULTIMA PROVA"); - - // let mut buf3 = Vec::new(); - // point_var_affine.value().unwrap() - // .serialize_with_mode(&mut buf3, Compress::No) - // .expect("serialization failed"); - // println!("STAMPO VEC SERIALIZE CIRCUIT"); - // for v in buf3.clone() { - // print!("{} - ", v); - // } - // println!(); - // let prova = point_var_affine.to_bytes()?; - // let vec2 = Vec::new(); - // for v in buf3.clone() { - // vec2.push(UInt8::); - // } - let mut bits = point_var_affine.to_bits_le()?; - let bytes: Vec> = bits - .chunks(8) - .map(|chunk| UInt8::from_bits_le(chunk)) - .collect(); - - println!("STAMPO VEC SERIALIZE CIRCUIT"); - for v in bytes.clone() { - print!("{} - ", v.value().unwrap()); - } - self.constraint_sponge.absorb(&bytes).unwrap(); - - let hash_var = self - .constraint_sponge - .squeeze_field_elements(1) - .unwrap() - .remove(0); - - println!("HASH_VAR: "); - println!("{}", hash_var.value().unwrap()); - - hash_var.enforce_equal(&exp_hash_var).unwrap(); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parameters::get_bls12377_fq_params; - use crate::transcript::Transcript; - use ark_bls12_377::constraints::G1Var; - use ark_bls12_377::{constraints::PairingVar as IV, constraints::*, Bls12_377 as I}; - use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; - use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; - use ark_crypto_primitives::sponge::poseidon::PoseidonSponge; - use ark_crypto_primitives::sponge::CryptographicSponge; - use ark_ec::bls12::Bls12; - use ark_ec::pairing::Pairing; - use ark_ff::{BigInteger, PrimeField}; - use ark_r1cs_std::{fields::fp::FpVar, groups::CurveVar, prelude::*}; - use ark_relations::{ns, r1cs::ConstraintSystem}; - use ark_std::test_rng; - use ark_std::UniformRand; - #[test] - fn absorb_test() { - let mut rng = test_rng(); - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - - let sponge_params = get_bls12377_fq_params(); - - let mut native_sponge = PoseidonTranscript::new(&sponge_params); - let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); - - let mut rng = ark_std::test_rng(); - let point = ark_bls12_377::G1Affine::rand(&mut rng); - let scalar = ark_bls12_377::Fr::rand(&mut rng); - let scalar_in_fq = - as Pairing>::BaseField::from_bigint(< as Pairing>::BaseField as PrimeField>::BigInt::from_bits_le( - scalar.into_bigint().to_bits_le().as_slice(), - )) - .unwrap(); - - //native_sponge.absorb(&point.clone()); - println!("POINT 1: "); - println!("{}", point); - native_sponge.append(b"U", &point); - - let hash = native_sponge - .challenge_scalar::< as Pairing>::BaseField>(b"random_point"); - - println!("HASH: "); - println!("{}", hash); - - // let point_var_affine = G1Var::new_input(cs.clone(), || Ok(point.clone())).unwrap(); - // constraint_sponge.absorb(&point_var_affine); - - // let scalar_var = FpVar::new_witness(cs.clone(), || Ok(scalar_in_fq)).unwrap(); - // let exp_hash_var = FpVar::new_witness(cs.clone(), || Ok(hash.clone())).unwrap(); - // constraint_sponge.absorb(&scalar_var); - let circuit: TestudoCommVerifier = TestudoCommVerifier { - native_sponge, - constraint_sponge, - point, - scalar_in_fq, - hash, - _iv: PhantomData, - }; - - circuit.generate_constraints(cs.clone()).unwrap(); - //let hash_var = constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); - //hash_var.enforce_equal(&exp_hash_var).unwrap(); - assert!(cs.is_satisfied().unwrap()); - } -} +// use crate::parameters::params_to_base_field; +// use crate::poseidon_transcript::PoseidonTranscript; +// use ark_bls12_377::constraints::G1Var; +// use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +// use ark_crypto_primitives::sponge::{ +// constraints::CryptographicSpongeVar, +// poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +// }; +// use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +// use ark_ec::CurveGroup; +// use ark_ec::pairing::Pairing; +// use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; +// use ark_r1cs_std::prelude::*; +// use ark_r1cs_std::{ +// alloc::AllocVar, +// fields::fp::FpVar, +// prelude::EqGadget, +// }; +// use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +// use ark_serialize::CanonicalSerialize; +// use ark_serialize::Compress; +// use std::marker::PhantomData; +// use ark_ff::PrimeField; +// use ark_ff::BigInteger; +// use ark_ec::AffineRepr; +// struct TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// { +// constraint_sponge: PoseidonSpongeVar, +// g1: E::G1Affine, +// hash: E::ScalarField, +// _iv: PhantomData, +// } + +// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, + +// { +// fn generate_constraints( +// mut self, +// cs: ConstraintSystemRef<::BaseField>, +// ) -> Result<(), SynthesisError> { + + +// // let hash_in_fq = &E::BaseField::from_bigint( +// // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), +// // ) +// // .unwrap(); + +// let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); + +// println!("REAL HASH VAR"); +// println!("{:?}", real_hash_var.value().unwrap()); + + +// // let scalar_in_fq = &E::BaseField::from_bigint( +// // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), +// // ) +// // .unwrap(); + + +// let g1_var = IV::G1Var::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; + +// // let x = self.g1.x().unwrap(); +// // let y = self.g1.y().unwrap(); + +// // let x_var = FpVar::new_input(cs.clone(), || Ok(x))?; + +// // let y_var = FpVar::new_input(cs.clone(), || Ok(y))?; + + + +// //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// // println!("x"); +// // println!("{:?}", x); + +// // println!("y"); +// // println!("{:?}", y); +// let mut buf3 = Vec::new(); +// g1_var.value().unwrap() +// .serialize_with_mode(&mut buf3, Compress::No) +// .expect("serialization failed"); + +// // println!("SCALAR VAR BYTES"); +// // println!("{:?}", buf3); + +// // self.constraint_sponge +// // .absorb(&x) +// // .unwrap(); + +// println!("G1 BYTES"); +// println!("{:?}", buf3); + +// let mut x_var_vec: Vec> = Vec::new(); +// for x in buf3 { +// x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); +// } +// self.constraint_sponge +// .absorb(&x_var_vec) +// .unwrap(); + +// let (hash_var1, hash_var2) = self.constraint_sponge +// .squeeze_nonnative_field_elements::(1) +// .unwrap(); +// // +// // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); +// println!("HASH_VAR 1: "); +// println!("{:?}", hash_var1.value().unwrap()); + +// // // for i in hash_var2 { +// // // println!("{:?}", i.value().unwrap()); +// // // } +// // // println!("HASH_VAR 2: "); +// // // println!("{:?}", hash_var2); +// real_hash_var.enforce_equal(&hash_var1[0]); +// Ok(()) +// } +// } + +// #[cfg(test)] +// mod tests { +// use super::*; +// use crate::parameters::get_bls12377_fq_params; +// use crate::parameters::poseidon_params; +// use crate::transcript::Transcript; +// use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; +// use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; +// use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; +// use ark_ec::bls12::Bls12; +// use ark_ec::pairing::Pairing; +// use ark_ff::{BigInteger, PrimeField}; +// use ark_relations::r1cs::ConstraintSystem; +// use ark_std::test_rng; +// use ark_std::UniformRand; +// use crate::parameters::get_bw6_fr_params; +// use ark_ec::bw6::BW6; +// #[test] +// fn absorb_test() { +// let mut rng = test_rng(); +// let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + +// let params = get_bw6_fr_params(); +// let sponge_params = get_bls12377_fq_params(); + +// // println!("SPONGE PARAMS BW6 FR"); +// // println!("{:?}",params); + +// // println!("SPONGE PARAMS BLS FQ"); +// // println!("{:?}",sponge_params); + +// let mut native_sponge = PoseidonTranscript::new(¶ms); +// let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); + +// let mut rng = ark_std::test_rng(); +// //let point = ark_bls12_377::G1Affine::rand(&mut rng); +// let g1 = ark_bls12_377::G1Affine::rand(&mut rng); + + +// let a = ark_ec::bls12::G1Prepared::default(); +// let b = ark_ec::bls12::G2Prepared::default(); +// let gt = ark_bls12_377::Bls12_377::pairing(a, b); + +// println!("G1 "); +// println!("{:?}", g1); + +// let mut buf = Vec::new(); +// g1 +// .serialize_with_mode(&mut buf, Compress::No) +// .expect("serialization failed"); + +// println!("G1 BYTES"); +// println!("{:?}", buf); + +// native_sponge.append(b"U", &g1); + +// let hash = native_sponge +// .challenge_scalar::< as ark_ec::pairing::Pairing>::ScalarField>(b"random_point"); + +// println!("HASH: "); +// println!("{:?}", hash); + +// let circuit: TestudoCommVerifier = TestudoCommVerifier { +// constraint_sponge, +// g1, +// hash, +// _iv: PhantomData, +// }; + +// circuit.generate_constraints(cs.clone()).unwrap(); +// assert!(cs.is_satisfied().unwrap()); +// } +// } \ No newline at end of file diff --git a/src/prova3.rs b/src/prova3.rs new file mode 100644 index 00000000..7518c0c8 --- /dev/null +++ b/src/prova3.rs @@ -0,0 +1,198 @@ +// use crate::parameters::params_to_base_field; +// use crate::poseidon_transcript::PoseidonTranscript; +// use ark_bls12_377::constraints::G1Var; +// use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +// use ark_crypto_primitives::sponge::{ +// constraints::CryptographicSpongeVar, +// poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +// }; +// use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +// use ark_ec::CurveGroup; +// use ark_ec::pairing::{Pairing, PairingOutput}; +// use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; +// use ark_r1cs_std::prelude::*; +// use ark_r1cs_std::{ +// alloc::AllocVar, +// fields::fp::FpVar, +// prelude::EqGadget, +// }; +// use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +// use ark_serialize::CanonicalSerialize; +// use ark_serialize::Compress; +// use std::marker::PhantomData; +// use ark_ff::PrimeField; +// use ark_ff::BigInteger; +// use ark_ec::AffineRepr; +// struct TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// { +// constraint_sponge: PoseidonSpongeVar, +// gt: PairingOutput, +// hash: E::ScalarField, +// _iv: PhantomData, +// } + +// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +// where +// E: Pairing, +// IV: PairingVar, +// IV::G1Var: CurveVar, +// IV::GTVar: FieldVar, + +// { +// fn generate_constraints( +// mut self, +// cs: ConstraintSystemRef<::BaseField>, +// ) -> Result<(), SynthesisError> { + + +// // let hash_in_fq = &E::BaseField::from_bigint( +// // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), +// // ) +// // .unwrap(); + +// let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); + +// println!("REAL HASH VAR"); +// println!("{:?}", real_hash_var.value().unwrap()); + + +// // let scalar_in_fq = &E::BaseField::from_bigint( +// // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), +// // ) +// // .unwrap(); + + +// let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; + +// // let x = self.g1.x().unwrap(); +// // let y = self.g1.y().unwrap(); + +// // let x_var = FpVar::new_input(cs.clone(), || Ok(x))?; + +// // let y_var = FpVar::new_input(cs.clone(), || Ok(y))?; + + + +// //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// // println!("x"); +// // println!("{:?}", x); + +// // println!("y"); +// // println!("{:?}", y); +// let mut buf3 = Vec::new(); +// gt_var.value().unwrap() +// .serialize_with_mode(&mut buf3, Compress::No) +// .expect("serialization failed"); + +// // println!("SCALAR VAR BYTES"); +// // println!("{:?}", buf3); + +// // self.constraint_sponge +// // .absorb(&x) +// // .unwrap(); + +// println!("G1 BYTES"); +// println!("{:?}", buf3); + +// let mut x_var_vec: Vec> = Vec::new(); +// for x in buf3 { +// x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); +// } +// self.constraint_sponge +// .absorb(&x_var_vec) +// .unwrap(); + +// let (hash_var1, hash_var2) = self.constraint_sponge +// .squeeze_nonnative_field_elements::(1) +// .unwrap(); + +// // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); +// println!("HASH_VAR 1: "); +// println!("{:?}", hash_var1.value().unwrap()); + +// // // for i in hash_var2 { +// // // println!("{:?}", i.value().unwrap()); +// // // } +// // // println!("HASH_VAR 2: "); +// // // println!("{:?}", hash_var2); +// real_hash_var.enforce_equal(&hash_var1[0]); +// Ok(()) +// } +// } + +// #[cfg(test)] +// mod tests { +// use super::*; +// use crate::parameters::get_bls12377_fq_params; +// use crate::parameters::poseidon_params; +// use crate::transcript::Transcript; +// use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; +// use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; +// use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; +// use ark_ec::bls12::Bls12; +// use ark_ec::pairing::Pairing; +// use ark_ff::{BigInteger, PrimeField}; +// use ark_relations::r1cs::ConstraintSystem; +// use ark_std::test_rng; +// use ark_std::UniformRand; +// use crate::parameters::get_bw6_fr_params; +// use ark_ec::bw6::BW6; +// #[test] +// fn absorb_test() { +// let mut rng = test_rng(); +// let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + +// let params = get_bw6_fr_params(); +// let sponge_params = get_bls12377_fq_params(); + +// // println!("SPONGE PARAMS BW6 FR"); +// // println!("{:?}",params); + +// // println!("SPONGE PARAMS BLS FQ"); +// // println!("{:?}",sponge_params); + +// let mut native_sponge = PoseidonTranscript::new(¶ms); +// let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); + +// let mut rng = ark_std::test_rng(); +// //let point = ark_bls12_377::G1Affine::rand(&mut rng); +// let g1 = ark_bls12_377::G1Affine::rand(&mut rng); + + +// let a = ark_ec::bls12::G1Prepared::default(); +// let b = ark_ec::bls12::G2Prepared::default(); +// let gt = ark_bls12_377::Bls12_377::pairing(a, b); + +// println!("G1 "); +// println!("{:?}", gt); + +// // let mut buf = Vec::new(); +// // g1 +// // .serialize_with_mode(&mut buf, Compress::No) +// // .expect("serialization failed"); + +// // println!("G1 BYTES"); +// // println!("{:?}", buf); + +// native_sponge.append(b"U", >); + +// let hash = native_sponge +// .challenge_scalar::< as ark_ec::pairing::Pairing>::ScalarField>(b"random_point"); + +// println!("HASH: "); +// println!("{:?}", hash); + +// let circuit: TestudoCommVerifier = TestudoCommVerifier { +// constraint_sponge, +// gt, +// hash, +// _iv: PhantomData, +// }; + +// circuit.generate_constraints(cs.clone()).unwrap(); +// assert!(cs.is_satisfied().unwrap()); +// } +// } \ No newline at end of file diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 92538529..1681d4a9 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -53,20 +53,20 @@ pub struct R1CSProof { #[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] pub struct R1CSVerifierProof { - comm: Commitment, - circuit_proof: ark_groth16::Proof, - initial_state: E::ScalarField, - transcript_sat_state: E::ScalarField, - eval_vars_at_ry: E::ScalarField, - proof_eval_vars_at_ry: Proof, - t: E::TargetField, - mipp_proof: MippProof, + pub comm: Commitment, + pub circuit_proof: ark_groth16::Proof, + pub initial_state: E::ScalarField, + pub transcript_sat_state: E::ScalarField, + pub eval_vars_at_ry: E::ScalarField, + pub proof_eval_vars_at_ry: Proof, + pub t: E::TargetField, + pub mipp_proof: MippProof, } #[derive(Clone)] pub struct CircuitGens { pk: ProvingKey, - vk: VerifyingKey, + pub vk: VerifyingKey, } impl CircuitGens @@ -152,8 +152,8 @@ where #[derive(Clone)] pub struct R1CSGens { - gens_pc: PolyCommitmentGens, - gens_gc: CircuitGens, + pub gens_pc: PolyCommitmentGens, + pub gens_gc: CircuitGens, } impl R1CSGens { @@ -488,11 +488,18 @@ where mod tests { use super::*; - + use ark_ec::CurveGroup; + use ark_ff::Field; +use ark_r1cs_std::pairing::PairingVar; + use crate::verifier_circuit::VerifierCircuit; + type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; use ark_ff::PrimeField; use ark_std::UniformRand; + use ark_relations::r1cs::ConstraintSystem; type F = ark_bls12_377::Fr; - + use crate::rand::SeedableRng; + use ark_relations::r1cs::ConstraintSynthesizer; + fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 // rounded to the nearest power of two @@ -566,25 +573,26 @@ mod tests { } use crate::parameters::PoseidonConfiguration; - #[test] - fn check_r1cs_proof_ark_blst() { - let params = ark_blst::Scalar::poseidon_params(); - check_r1cs_proof::(params); - } + //#[test] + // fn check_r1cs_proof_ark_blst() { + // let params = ark_blst::Scalar::poseidon_params(); + // check_r1cs_proof::(params); + // } #[test] fn check_r1cs_proof_bls12_377() { let params = ark_bls12_377::Fr::poseidon_params(); - check_r1cs_proof::(params); + check_r1cs_proof::(params); } - #[test] - fn check_r1cs_proof_bls12_381() { - let params = ark_bls12_381::Fr::poseidon_params(); - check_r1cs_proof::(params); - } - fn check_r1cs_proof

(params: PoseidonConfig) + //#[test] + // fn check_r1cs_proof_bls12_381() { + // let params = ark_bls12_381::Fr::poseidon_params(); + // check_r1cs_proof::(params); + // } + fn check_r1cs_proof(params: PoseidonConfig) where P: Pairing, + IV: PairingVar>, P::ScalarField: PrimeField, P::ScalarField: Absorb, { @@ -620,14 +628,22 @@ mod tests { .unwrap(); let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); - assert!(verifer_proof - .verify( - (rx, ry), - &input, - &inst_evals, - &mut verifier_transcript, - &gens - ) - .is_ok()); + // assert!(verifer_proof + // .verify( + // (rx, ry), + // &input, + // &inst_evals, + // &mut verifier_transcript, + // &gens + // ) + // .is_ok()); + let mut rng = rand_chacha::ChaChaRng::seed_from_u64(1776); + let cs = ConstraintSystem::>::new_ref(); + let circuit = VerifierCircuit::::new((rx, ry),input,inst_evals,verifier_transcript,gens,verifer_proof).unwrap(); + circuit.generate_constraints(cs.clone()); + // .unwrap(); + assert!(cs.is_satisfied().unwrap()); + + } -} +} \ No newline at end of file diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index a513f6d9..e4aec374 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -300,7 +300,7 @@ mod tests { check_sqrt_poly_commit(5); // check even case - //check_sqrt_poly_commit(6); + check_sqrt_poly_commit(6); } fn check_sqrt_poly_commit(num_vars: u32) { diff --git a/src/verifier_circuit.rs b/src/verifier_circuit.rs new file mode 100644 index 00000000..2304d2e8 --- /dev/null +++ b/src/verifier_circuit.rs @@ -0,0 +1,150 @@ +use crate::ark_std::One; +use crate::constraints::R1CSVerificationCircuit; +use crate::mipp::MippProof; +use crate::parameters::get_bls12377_fq_params; +use crate::parameters::params_to_base_field; +use crate::r1csproof::R1CSGens; +use crate::r1csproof::R1CSVerifierProof; +use crate::constraints::VerifierConfig; +use crate::{ + math::Math, + poseidon_transcript::PoseidonTranscript, + sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, + unipoly::UniPoly, +}; +use ark_crypto_primitives::snark::SNARKGadget; +use ark_ec::CurveGroup; +use ark_ff::Field; +use ark_groth16::constraints::Groth16VerifierGadget; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::Error; +use ark_ec::pairing::Pairing; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_groth16::Groth16; +use ark_groth16::PreparedVerifyingKey; +use ark_groth16::constraints::PreparedVerifyingKeyVar; +use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +use ark_poly_commit::multilinear_pc::{ + data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, + MultilinearPC, +}; +use ark_r1cs_std::groups::bls12::G1Var; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::{ + alloc::{AllocVar, AllocationMode}, + fields::fp::FpVar, + prelude::{EqGadget, FieldVar}, +}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +use ark_serialize::Compress; +use ark_snark::CircuitSpecificSetupSNARK; +use ark_snark::SNARK; +use digest::generic_array::typenum::True; +use rand::CryptoRng; +use rand::Rng; +use std::ops::AddAssign; +use std::ops::Mul; +use std::ops::MulAssign; +use std::{borrow::Borrow, marker::PhantomData}; +use ark_groth16; +type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; + +pub struct VerifierCircuit +where + E: Pairing, + IV: PairingVar>, +{ + // pub inner_circuit: R1CSVerificationCircuit, // circuito Mara + + // pub inner_proof: ark_groth16::Proof, // PROOF DA VERIFICARE + // pub inner_vk: PreparedVerifyingKey, // GENS.GC.VK + + pub r: (Vec, Vec), + pub input: Vec, + pub evals: (E::ScalarField,E::ScalarField,E::ScalarField), + + pub transcript: PoseidonTranscript, + pub gens: R1CSGens, + pub r1cs_proof: R1CSVerifierProof, // SELF + pub _iv: PhantomData, +} + +impl VerifierCircuit +where + E: Pairing, + IV: PairingVar>, +{ + pub fn new( + //config: &VerifierConfig, + //mut rng: &mut R, + r: (Vec, Vec), + input: Vec, + evals: (E::ScalarField, E::ScalarField, E::ScalarField), + transcript: PoseidonTranscript, + gens: R1CSGens, + r1cs_proof: R1CSVerifierProof, + ) -> Result { + // let inner_circuit = crate::constraints::R1CSVerificationCircuit::new(config); + // let (pk, vk) = Groth16::::setup(inner_circuit.clone(), &mut rng).unwrap(); + // let proof = Groth16::::prove(&pk, inner_circuit.clone(), &mut rng)?; + // let pvk = Groth16::::process_vk(&vk).unwrap(); + Ok(Self { + // inner_circuit, + // inner_proof: proof, + // inner_vk: pvk, + r: r, + input: input.to_vec(), + evals: evals, + transcript: transcript, + gens: gens, + r1cs_proof, + _iv: PhantomData, + }) + } +} +impl ConstraintSynthesizer> for VerifierCircuit +where +E: Pairing, +IV: PairingVar>, + +//IV::G1Var: CurveVar, +// IV::G2Var: CurveVar, +// IV::GTVar: FieldVar, +{ + fn generate_constraints(self, cs: ConstraintSystemRef>) -> ark_relations::r1cs::Result<()> { + + // //STEP 1) ALLOCATE INNER_PROOF AS CIRCUIT VARIABLE + + let (rx, ry) = self.r; + let (Ar, Br, Cr) = self.evals; + let mut pubs = vec![self.r1cs_proof.initial_state]; + pubs.extend(self.input.clone()); + pubs.extend(rx.clone()); + pubs.extend(ry.clone()); + pubs.extend(vec![ + self.r1cs_proof.eval_vars_at_ry, + Ar, + Br, + Cr, + self.r1cs_proof.transcript_sat_state, + ]); + // self.transcript.new_from_state(self.r1cs_proof.transcript_sat_state); + + + + let proof_gadget = as SNARKGadget,Groth16>>::ProofVar::new_witness(cs.clone(), || Ok(self.r1cs_proof.circuit_proof)).unwrap(); + let vk_gadget = as SNARKGadget,Groth16>>::VerifyingKeyVar::new_witness(cs.clone(), || Ok(self.gens.gens_gc.vk.clone())).unwrap(); + + let input_gadget= as SNARKGadget,Groth16>>::InputVar::new_input(cs.clone(), || Ok(pubs)).unwrap(); + let ver = as SNARKGadget,Groth16>>::verify(&vk_gadget, &input_gadget, &proof_gadget).unwrap(); + println!("Verifier groth circuit"); + ver.enforce_equal(&Boolean::constant(true)).unwrap(); + Ok(()) + } +} \ No newline at end of file From 1062c3c0774e71a3a8925ba4c8cca282d570b56b Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Tue, 28 Nov 2023 18:26:48 +0100 Subject: [PATCH 14/21] feat: check poseidon function from native to circuit --- src/prova.rs | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/prova.rs b/src/prova.rs index 528cae2e..00a4ffc5 100644 --- a/src/prova.rs +++ b/src/prova.rs @@ -54,7 +54,7 @@ where // // ) // // .unwrap(); - // let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.scalar))?; + let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.scalar))?; // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; // // println!("SCALAR VAR"); @@ -112,16 +112,20 @@ where // .unwrap(); // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - let cv = NonNativeFieldVar::::new_witness(cs.clone(), || { - Ok(self.scalar.clone()) - })?; - println!("Scalar {:?}", cv.value().unwrap()); - println!("CF {:?}", cv.to_constraint_field()?.value().unwrap()); - sponge.absorb(&cv.to_constraint_field()?); - let hash = sponge.squeeze_nonnative_field_elements::(1)?; - - println!("hash {:?}", hash.0.value().unwrap()); + + println!("Scalar {:?}", scalar_var.value().unwrap()); + + sponge.absorb(&scalar_var.to_bytes().unwrap()); + let hash = sponge.squeeze_nonnative_field_elements::(1); + + println!("hash {:?}", hash.unwrap().0.value().unwrap()); // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] Ok(()) } @@ -143,13 +147,13 @@ mod tests { use ark_relations::r1cs::ConstraintSystem; use ark_std::test_rng; use ark_std::UniformRand; + #[test] fn absorb_test() { let mut rng = test_rng(); let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - let params = poseidon_params(); - + let params = get_bls12377_fq_params(); let mut native_sponge = PoseidonTranscript::new(¶ms); let mut rng = ark_std::test_rng(); //let point = ark_bls12_377::G1Affine::rand(&mut rng); @@ -160,29 +164,18 @@ mod tests { native_sponge.append(b"U", &scalar); - let hash: ark_bls12_377::Fr = native_sponge.challenge_scalar(b"random_point"); + let hash = native_sponge.challenge_scalar::(b"random_point"); println!("HASH: "); println!("{:?}", hash); let circuit: TestudoCommVerifier = TestudoCommVerifier { - scalar, + scalar: ark_bls12_377::Fr::from(5 as u8), poseidon_params: get_bls12377_fq_params(), _iv: PhantomData, }; circuit.generate_constraints(cs.clone()).unwrap(); assert!(cs.is_satisfied().unwrap()); - - let params = get_bls12377_fq_params(); - - let mut native_sponge2 = PoseidonTranscript::new(¶ms); - - native_sponge2.append(b"U", &scalar); - - let hash2: ark_bls12_377::Fr = native_sponge2.challenge_scalar(b"random_point"); - - println!("HASH2: "); - println!("{:?}", hash2); } } From 4bcda28179496d30895fadc3ea3c6ba1cb576f15 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Wed, 29 Nov 2023 15:55:15 +0100 Subject: [PATCH 15/21] feat: hash non native inside the circuit --- src/circuit_verifier.rs | 324 +++++----- src/mipp.rs | 6 +- src/prova2.rs | 388 ++++++------ src/prova3.rs | 201 ++++++ src/r1csproof.rs | 1297 ++++++++++++++++++++------------------- src/sqrt_pst.rs | 10 +- src/testudo_nizk.rs | 404 ++++++------ src/testudo_snark.rs | 754 +++++++++++------------ src/verifier_circuit.rs | 727 +++++++++++++++++----- 9 files changed, 2366 insertions(+), 1745 deletions(-) diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index dbc1a21a..dd66790d 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -33,6 +33,7 @@ use ark_r1cs_std::{ fields::fp::FpVar, prelude::{EqGadget, FieldVar}, }; +use ark_ff::Field; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; @@ -91,7 +92,6 @@ where E: Pairing, IV: PairingVar, { - pub state: E::ScalarField, pub vk: VerifierKey, pub U: Commitment, pub point: Vec, @@ -108,7 +108,6 @@ where { fn clone(&self) -> Self { Self { - state: self.state.clone(), vk: self.vk.clone(), U: self.U.clone(), point: self.point.clone(), @@ -137,49 +136,33 @@ where cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { // allocate point - let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); - let state_var = - NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.state)) - .unwrap(); - - println!("STATE VAR {:?}", state_var.value().unwrap()); - - let mut x_var_vec: Vec> = Vec::new(); - for x in state_var.to_bytes()?.value().unwrap() { - x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - } - constraint_sponge.absorb(&x_var_vec).unwrap(); - - let (hash_var1, hash_var2) = constraint_sponge - .squeeze_nonnative_field_elements::(1) + let mut point_var = Vec::new(); + for p in self.point.clone().into_iter() { + let scalar_in_fq = &E::BaseField::from_bigint( + ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), + ) .unwrap(); - println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); - // let mut point_var = Vec::new(); - // for p in self.point.clone().into_iter() { - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - // let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - // point_var.push(p_var); - // } - // let len = point_var.len(); - // let odd = if len % 2 == 1 { 1 } else { 0 }; - // let a_var = &point_var[0..len / 2 + odd]; - // let b_var = &point_var[len / 2 + odd..len]; - - // let res_mipp = mipp_verify_gadget::( - // cs.clone(), - // self.vk.clone(), - // &self.mipp_proof, - // b_var.to_vec(), - // self.U.g_product, - // &self.T, - // ); - - // assert!(res_mipp.unwrap() == true); - // let mut a_rev_var = a_var.to_vec().clone(); - // a_rev_var.reverse(); + let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + //let p_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(p))?; + point_var.push(p_var); + } + let len = point_var.len(); + let odd = if len % 2 == 1 { 1 } else { 0 }; + let a_var = &point_var[0..len / 2 + odd]; + let b_var = &point_var[len / 2 + odd..len]; + + let res_mipp = mipp_verify_gadget::( + cs.clone(), + self.vk.clone(), + &self.mipp_proof, + b_var.to_vec(), + self.U.g_product, + &self.T, + ); + + assert!(res_mipp.unwrap() == true); + let mut a_rev_var = a_var.to_vec().clone(); + a_rev_var.reverse(); // let res_var = check_gadget::( // cs.clone(), @@ -189,7 +172,7 @@ where // self.v, // self.pst_proof, // ); - // assert!(res_var.unwrap() == true); + //assert!(res_var.unwrap() == true); Ok(()) } } @@ -379,20 +362,17 @@ where let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); // PRIMA ABSORB - let mut U_g_product_buf = Vec::new(); - U_g_product_var - .value() - .unwrap() - .serialize_with_mode(&mut U_g_product_buf, Compress::No) + let mut buf = Vec::new(); + U_g_product_var.value().unwrap().into_affine() + .serialize_with_mode(&mut buf, Compress::No) .expect("serialization failed"); - let mut U_g_product_var_bytes = Vec::new(); - - for b in U_g_product_buf { - U_g_product_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + let mut u_var_vec: Vec> = Vec::new(); + for el in buf { + u_var_vec.push(UInt8::new_input(cs.clone(), || Ok(el))?); } - - transcript_var.absorb(&U_g_product_var_bytes)?; + println!("Circ - Prima absorb: {:?}",U_g_product_var.value().unwrap().into_affine()); + transcript_var.absorb(&u_var_vec); let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { @@ -404,6 +384,7 @@ where comm_u_l .value() .unwrap() + .into_affine() .serialize_with_mode(&mut comm_u_l_buf, Compress::No) .expect("serialization failed"); @@ -418,6 +399,7 @@ where comm_u_r .value() .unwrap() + .into_affine() .serialize_with_mode(&mut comm_u_r_buf, Compress::No) .expect("serialization failed"); @@ -456,108 +438,107 @@ where } transcript_var.absorb(&comm_t_r_var_bytes)?; - let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + // AIAIAIAIAIA + + let c_inv_var = (transcript_var.squeeze_nonnative_field_elements::(1)?).0.value().unwrap()[0]; + println!("CIRC SQUEEZY: {:?}", c_inv_var); let c_var = c_inv_var.inverse().unwrap(); - println!("PRIMA SQUEEZY CIRCUIT"); - println!("{}", c_inv_var.value().unwrap()); - break; xs.push(c_var.clone()); xs_inv.push(c_inv_var.clone()); final_y_var *= &one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; } - enum Op<'a, E: Pairing, IV: PairingVar> { - TC(&'a IV::GTVar, FpVar<::BaseField>), // BigInt == FpVar - UC(&'a IV::G1Var, &'a FpVar<::BaseField>), - } - - let res_var = comms_t_var - .iter() - .zip(comms_u_var.iter()) - .zip(xs.iter().zip(xs_inv.iter())) - .flat_map(|((comm_t, comm_u), (c, c_inv))| { - let (comm_t_l, comm_t_r) = comm_t; - let (comm_u_l, comm_u_r) = comm_u; - - // we multiple left side by x^-1 and right side by x - vec![ - Op::TC(comm_t_l, c_inv.clone()), - Op::TC(comm_t_r, c.clone()), - Op::UC(comm_u_l, c_inv), - Op::UC(comm_u_r, c), - ] - }) - .fold(MippTUVar::::default(), |mut res, op: Op| { - match op { - Op::TC(tx, c) => { - // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; - let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); - res.tc.mul_assign(&tx); - } - Op::UC(zx, c) => { - let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); - res.uc.add_assign(&uxp); - } - } - res - }); - - let ref_final_res_var = &mut final_res_var; - ref_final_res_var.merge(&res_var); - - let mut rs: Vec::BaseField>> = Vec::new(); - let m = xs_inv.len(); - for _i in 0..m { - let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - rs.push(r); - } - println!("SONO QUA"); - println!("{}", rs[0].value().unwrap()); - // let rs_var = rs.clone(); - let v_var: FpVar<::BaseField> = (0..m) - .into_iter() - .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) - .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold - - let comm_h = CommitmentG2:: { - nv: m, - h_product: proof.final_h, - }; - - let check_h_var = check_2_gadget::( - cs.clone(), - vk.clone(), - &comm_h, - &rs, - v_var, - &proof.pst_proof_h, - ); - let check_h = check_h_var.unwrap(); - assert!(check_h.clone() == true); - let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; - let final_u_var = final_a_var - .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) - .unwrap(); - - let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; - - let final_u_var_prep = IV::prepare_g1(&final_a_var)?; - let final_h_var_prep = IV::prepare_g2(&final_h_var)?; - - let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; - let check_t = true; - - //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); - - assert!(check_t == true); - - let check_u = true; - //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { - - assert!(check_u == true); - Ok(check_h & check_u) + // enum Op<'a, E: Pairing, IV: PairingVar> { + // TC(&'a IV::GTVar, FpVar<::BaseField>), // BigInt == FpVar + // UC(&'a IV::G1Var, &'a FpVar<::BaseField>), + // } + + // let res_var = comms_t_var + // .iter() + // .zip(comms_u_var.iter()) + // .zip(xs.iter().zip(xs_inv.iter())) + // .flat_map(|((comm_t, comm_u), (c, c_inv))| { + // let (comm_t_l, comm_t_r) = comm_t; + // let (comm_u_l, comm_u_r) = comm_u; + + // // we multiple left side by x^-1 and right side by x + // vec![ + // Op::TC(comm_t_l, c_inv.clone()), + // Op::TC(comm_t_r, c.clone()), + // Op::UC(comm_u_l, c_inv), + // Op::UC(comm_u_r, c), + // ] + // }) + // .fold(MippTUVar::::default(), |mut res, op: Op| { + // match op { + // Op::TC(tx, c) => { + // // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; + // let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); + // res.tc.mul_assign(&tx); + // } + // Op::UC(zx, c) => { + // let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); + // res.uc.add_assign(&uxp); + // } + // } + // res + // }); + + // let ref_final_res_var = &mut final_res_var; + // ref_final_res_var.merge(&res_var); + + // let mut rs: Vec::BaseField>> = Vec::new(); + // let m = xs_inv.len(); + // for _i in 0..m { + // let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); + // rs.push(r); + // } + // // let rs_var = rs.clone(); + // let v_var: FpVar<::BaseField> = (0..m) + // .into_iter() + // .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) + // .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold + + // let comm_h = CommitmentG2:: { + // nv: m, + // h_product: proof.final_h, + // }; + + // let check_h_var = check_2_gadget::( + // cs.clone(), + // vk.clone(), + // &comm_h, + // &rs, + // v_var, + // &proof.pst_proof_h, + // ); + // let check_h = check_h_var.unwrap(); + // assert!(check_h.clone() == true); + // let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; + // let final_u_var = final_a_var + // .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) + // .unwrap(); + + // let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; + + // let final_u_var_prep = IV::prepare_g1(&final_a_var)?; + // let final_h_var_prep = IV::prepare_g2(&final_h_var)?; + + // let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; + // let check_t = true; + + // //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); + + // assert!(check_t == true); + + // let check_u = true; + // //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { + + // assert!(check_u == true); + // Ok(check_h & check_u) + Ok(true) } #[cfg(test)] mod tests { @@ -614,24 +595,37 @@ mod tests { let (comm_list, t) = pl.commit(&ck); let params = poseidon_params(); - let mut prover_transcript = PoseidonTranscript::new(¶ms); + let mut prover_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - // let circuit = TestudoCommVerifier { - // vk, - // U: u, - // point: r, - // v, - // pst_proof, - // mipp_proof, - // T: t, - // _iv: PhantomData::, - // }; - - // let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - // circuit.generate_constraints(cs.clone()).unwrap(); - // assert!(cs.is_satisfied().unwrap()); + let mut verifier_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + + let res = Polynomial::verify( + &mut verifier_transcript, + &vk, + &u, + &r, + v, + &pst_proof, + &mipp_proof, + &t, + ); + assert!(res == true); + + let circuit = TestudoCommVerifier::{ + vk, + U: u, + point: r, + v, + pst_proof, + mipp_proof, + T: t, + _iv: PhantomData, + }; + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + circuit.generate_constraints(cs.clone()).unwrap(); + assert!(cs.is_satisfied().unwrap()); // let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); // let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); diff --git a/src/mipp.rs b/src/mipp.rs index 22ed3249..c8b967f9 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -29,7 +29,7 @@ pub struct MippProof { impl MippProof { pub fn prove( - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, ck: &CommitterKey, a: Vec, y: Vec, @@ -181,7 +181,7 @@ impl MippProof { pub fn verify( vk: &VerifierKey, - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, proof: &MippProof, point: Vec, U: &E::G1Affine, @@ -199,6 +199,7 @@ impl MippProof { uc: U.into_group(), }; + println!("VER - Prima absorb: {:?}",U); transcript.append(b"U", U); // Challenges need to be generated first in sequential order so the @@ -213,6 +214,7 @@ impl MippProof { transcript.append(b"comm_t_l", comm_t_l); transcript.append(b"comm_t_r", comm_t_r); let c_inv = transcript.challenge_scalar::(b"challenge_i"); + println!("NAIV SQUEEZY: {:?}", c_inv); let c = c_inv.inverse().unwrap(); xs.push(c); diff --git a/src/prova2.rs b/src/prova2.rs index e6571e2b..c024c130 100644 --- a/src/prova2.rs +++ b/src/prova2.rs @@ -1,197 +1,193 @@ -// use crate::parameters::params_to_base_field; -// use crate::poseidon_transcript::PoseidonTranscript; -// use ark_bls12_377::constraints::G1Var; -// use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -// use ark_crypto_primitives::sponge::{ -// constraints::CryptographicSpongeVar, -// poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -// }; -// use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -// use ark_ec::CurveGroup; -// use ark_ec::pairing::Pairing; -// use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -// use ark_r1cs_std::prelude::*; -// use ark_r1cs_std::{ -// alloc::AllocVar, -// fields::fp::FpVar, -// prelude::EqGadget, -// }; -// use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -// use ark_serialize::CanonicalSerialize; -// use ark_serialize::Compress; -// use std::marker::PhantomData; -// use ark_ff::PrimeField; -// use ark_ff::BigInteger; -// use ark_ec::AffineRepr; -// struct TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// { -// constraint_sponge: PoseidonSpongeVar, -// g1: E::G1Affine, -// hash: E::ScalarField, -// _iv: PhantomData, -// } - -// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, - -// { -// fn generate_constraints( -// mut self, -// cs: ConstraintSystemRef<::BaseField>, -// ) -> Result<(), SynthesisError> { +use crate::parameters::params_to_base_field; +use crate::poseidon_transcript::PoseidonTranscript; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +use ark_ec::pairing::Pairing; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::ToConstraintFieldGadget; +use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +use ark_serialize::CanonicalSerialize; +use ark_serialize::Compress; +use poseidon_parameters::PoseidonParameters; +use std::marker::PhantomData; +use ark_ec::CurveGroup; +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + g1: E::G1Affine, + poseidon_params: PoseidonConfig, + _iv: PhantomData, +} + +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, +{ + fn generate_constraints( + mut self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + // let hash_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); + + // println!("REAL HASH VAR"); + // println!("{:?}", real_hash_var.value().unwrap()); + + // // let scalar_in_fq = &E::BaseField::from_bigint( + // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // // ) + // // .unwrap(); + + let g1_var = IV::G1Var::new_input(cs.clone(), || Ok(self.g1))?; + + + //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; + + // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // // println!("SCALAR VAR"); + // // println!("{:?}", scalar_var.value().unwrap()); + + // // let mut buf3 = Vec::new(); + // // scalar_var.value().unwrap() + // // .serialize_with_mode(&mut buf3, Compress::Yes) + // // .expect("serialization failed"); + + // // println!("SCALAR VAR BYTES"); + // // println!("{:?}", buf3); + + // self.constraint_sponge + // .absorb(&scalar_var.to_bytes()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = self.constraint_sponge + // .squeeze_nonnative_field_elements::(1) + // .unwrap(); + + // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); + // println!("HASH_VAR 1: "); + // println!("{:?}", hash_var1.value().unwrap()); + + // // for i in hash_var2 { + // // println!("{:?}", i.value().unwrap()); + // // } + // // println!("HASH_VAR 2: "); + // // println!("{:?}", hash_var2); + // real_hash_var.enforce_equal(&hash_var1[0]); + + // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); + // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); + + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + + // println!("STATE VAR {:?}", state_var.value().unwrap()); + + // let mut x_var_vec: Vec> = Vec::new(); + // for x in state_var.to_bytes()?.value().unwrap() { + // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + // } + // constraint_sponge + // .absorb(&scalar_in_fq()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = constraint_sponge + // .squeeze_nonnative_field_elements::(1).unwrap().pop() + // .unwrap(); + // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); + + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - -// // let hash_in_fq = &E::BaseField::from_bigint( -// // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), -// // ) -// // .unwrap(); - -// let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); - -// println!("REAL HASH VAR"); -// println!("{:?}", real_hash_var.value().unwrap()); - - -// // let scalar_in_fq = &E::BaseField::from_bigint( -// // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), -// // ) -// // .unwrap(); - - -// let g1_var = IV::G1Var::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; - -// // let x = self.g1.x().unwrap(); -// // let y = self.g1.y().unwrap(); - -// // let x_var = FpVar::new_input(cs.clone(), || Ok(x))?; - -// // let y_var = FpVar::new_input(cs.clone(), || Ok(y))?; - - - -// //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; -// // println!("x"); -// // println!("{:?}", x); - -// // println!("y"); -// // println!("{:?}", y); -// let mut buf3 = Vec::new(); -// g1_var.value().unwrap() -// .serialize_with_mode(&mut buf3, Compress::No) -// .expect("serialization failed"); - -// // println!("SCALAR VAR BYTES"); -// // println!("{:?}", buf3); - -// // self.constraint_sponge -// // .absorb(&x) -// // .unwrap(); - -// println!("G1 BYTES"); -// println!("{:?}", buf3); - -// let mut x_var_vec: Vec> = Vec::new(); -// for x in buf3 { -// x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); -// } -// self.constraint_sponge -// .absorb(&x_var_vec) -// .unwrap(); - -// let (hash_var1, hash_var2) = self.constraint_sponge -// .squeeze_nonnative_field_elements::(1) -// .unwrap(); -// // -// // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); -// println!("HASH_VAR 1: "); -// println!("{:?}", hash_var1.value().unwrap()); - -// // // for i in hash_var2 { -// // // println!("{:?}", i.value().unwrap()); -// // // } -// // // println!("HASH_VAR 2: "); -// // // println!("{:?}", hash_var2); -// real_hash_var.enforce_equal(&hash_var1[0]); -// Ok(()) -// } -// } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::parameters::get_bls12377_fq_params; -// use crate::parameters::poseidon_params; -// use crate::transcript::Transcript; -// use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; -// use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; -// use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; -// use ark_ec::bls12::Bls12; -// use ark_ec::pairing::Pairing; -// use ark_ff::{BigInteger, PrimeField}; -// use ark_relations::r1cs::ConstraintSystem; -// use ark_std::test_rng; -// use ark_std::UniformRand; -// use crate::parameters::get_bw6_fr_params; -// use ark_ec::bw6::BW6; -// #[test] -// fn absorb_test() { -// let mut rng = test_rng(); -// let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - -// let params = get_bw6_fr_params(); -// let sponge_params = get_bls12377_fq_params(); - -// // println!("SPONGE PARAMS BW6 FR"); -// // println!("{:?}",params); - -// // println!("SPONGE PARAMS BLS FQ"); -// // println!("{:?}",sponge_params); - -// let mut native_sponge = PoseidonTranscript::new(¶ms); -// let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); - -// let mut rng = ark_std::test_rng(); -// //let point = ark_bls12_377::G1Affine::rand(&mut rng); -// let g1 = ark_bls12_377::G1Affine::rand(&mut rng); - - -// let a = ark_ec::bls12::G1Prepared::default(); -// let b = ark_ec::bls12::G2Prepared::default(); -// let gt = ark_bls12_377::Bls12_377::pairing(a, b); - -// println!("G1 "); -// println!("{:?}", g1); - -// let mut buf = Vec::new(); -// g1 -// .serialize_with_mode(&mut buf, Compress::No) -// .expect("serialization failed"); - -// println!("G1 BYTES"); -// println!("{:?}", buf); - -// native_sponge.append(b"U", &g1); - -// let hash = native_sponge -// .challenge_scalar::< as ark_ec::pairing::Pairing>::ScalarField>(b"random_point"); - -// println!("HASH: "); -// println!("{:?}", hash); - -// let circuit: TestudoCommVerifier = TestudoCommVerifier { -// constraint_sponge, -// g1, -// hash, -// _iv: PhantomData, -// }; - -// circuit.generate_constraints(cs.clone()).unwrap(); -// assert!(cs.is_satisfied().unwrap()); -// } -// } \ No newline at end of file + println!("g1 {:?}", g1_var.value().unwrap().into_affine()); + + let mut buf3 = Vec::new(); + g1_var.value().unwrap().into_affine() + .serialize_with_mode(&mut buf3, Compress::No) + .expect("serialization failed"); + + let mut x_var_vec: Vec> = Vec::new(); + for x in buf3 { + x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + } + sponge.absorb(&x_var_vec); + let hash = sponge.squeeze_nonnative_field_elements::(1); + + println!("hash {:?}", hash.unwrap().0.value().unwrap()); + // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::parameters::get_bls12377_fq_params; + use crate::parameters::get_bw6_fr_params; + use crate::parameters::poseidon_params; + use crate::transcript::Transcript; + use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; + use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; + use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; + use ark_ec::bls12::Bls12; + use ark_ec::pairing::Pairing; + use ark_ff::{BigInteger, PrimeField}; + use ark_relations::r1cs::ConstraintSystem; + use ark_std::test_rng; + use ark_std::UniformRand; + + #[test] + fn absorb_test() { + let mut rng = test_rng(); + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + + let params = get_bls12377_fq_params(); + let mut native_sponge = PoseidonTranscript::new(¶ms); + let mut rng = ark_std::test_rng(); + //let point = ark_bls12_377::G1Affine::rand(&mut rng); + let g1 = ark_bls12_377::g1::G1Affine::rand(&mut rng); + + println!("G1 "); + println!("{:?}", g1); + + native_sponge.append(b"U", &g1); + + let hash = native_sponge.challenge_scalar::(b"random_point"); + + println!("HASH: "); + println!("{:?}", hash); + + let circuit: TestudoCommVerifier = TestudoCommVerifier { + g1, + poseidon_params: get_bls12377_fq_params(), + _iv: PhantomData, + }; + + circuit.generate_constraints(cs.clone()).unwrap(); + assert!(cs.is_satisfied().unwrap()); + } +} diff --git a/src/prova3.rs b/src/prova3.rs index 7518c0c8..94bb36f5 100644 --- a/src/prova3.rs +++ b/src/prova3.rs @@ -1,3 +1,204 @@ +use crate::parameters::params_to_base_field; +use crate::poseidon_transcript::PoseidonTranscript; +use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; +use ark_ec::pairing::{Pairing, PairingOutput}; +use ark_ff::BigInteger; +use ark_ff::PrimeField; +use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; +use ark_r1cs_std::prelude::*; +use ark_r1cs_std::ToConstraintFieldGadget; +use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; +use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; +use ark_serialize::CanonicalSerialize; +use ark_serialize::Compress; +use poseidon_parameters::PoseidonParameters; +use std::marker::PhantomData; +use ark_ec::CurveGroup; +struct TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, +{ + gt: PairingOutput, + poseidon_params: PoseidonConfig, + _iv: PhantomData, +} + +impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier +where + E: Pairing, + IV: PairingVar, + IV::G1Var: CurveVar, + IV::GTVar: FieldVar, +{ + fn generate_constraints( + mut self, + cs: ConstraintSystemRef<::BaseField>, + ) -> Result<(), SynthesisError> { + // let hash_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); + + // println!("REAL HASH VAR"); + // println!("{:?}", real_hash_var.value().unwrap()); + + // // let scalar_in_fq = &E::BaseField::from_bigint( + // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // // ) + // // .unwrap(); + + let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; + + + //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; + + // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + // // println!("SCALAR VAR"); + // // println!("{:?}", scalar_var.value().unwrap()); + + // // let mut buf3 = Vec::new(); + // // scalar_var.value().unwrap() + // // .serialize_with_mode(&mut buf3, Compress::Yes) + // // .expect("serialization failed"); + + // // println!("SCALAR VAR BYTES"); + // // println!("{:?}", buf3); + + // self.constraint_sponge + // .absorb(&scalar_var.to_bytes()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = self.constraint_sponge + // .squeeze_nonnative_field_elements::(1) + // .unwrap(); + + // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); + // println!("HASH_VAR 1: "); + // println!("{:?}", hash_var1.value().unwrap()); + + // // for i in hash_var2 { + // // println!("{:?}", i.value().unwrap()); + // // } + // // println!("HASH_VAR 2: "); + // // println!("{:?}", hash_var2); + // real_hash_var.enforce_equal(&hash_var1[0]); + + // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); + // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); + + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + + // println!("STATE VAR {:?}", state_var.value().unwrap()); + + // let mut x_var_vec: Vec> = Vec::new(); + // for x in state_var.to_bytes()?.value().unwrap() { + // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + // } + // constraint_sponge + // .absorb(&scalar_in_fq()?) + // .unwrap(); + + // let (hash_var1, hash_var2) = constraint_sponge + // .squeeze_nonnative_field_elements::(1).unwrap().pop() + // .unwrap(); + // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); + + // let scalar_in_fq = &E::BaseField::from_bigint( + // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), + // ) + // .unwrap(); + + // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); + + println!("gt {:?}", gt_var.value().unwrap()); + + let mut buf3 = Vec::new(); + gt_var + .value() + .unwrap() + .serialize_with_mode(&mut buf3, Compress::No) + .expect("serialization failed"); + + let mut x_var_vec: Vec> = Vec::new(); + for x in buf3 { + x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); + } + sponge.absorb(&x_var_vec); + let hash = sponge.squeeze_nonnative_field_elements::(1); + + println!("hash {:?}", hash.unwrap().0.value().unwrap()); + // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::parameters::get_bls12377_fq_params; + use crate::parameters::get_bw6_fr_params; + use crate::parameters::poseidon_params; + use crate::transcript::Transcript; + use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; + use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; + use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; + use ark_ec::bls12::Bls12; + use ark_ec::pairing::Pairing; + use ark_ff::{BigInteger, PrimeField}; + use ark_relations::r1cs::ConstraintSystem; + use ark_std::test_rng; + use ark_std::UniformRand; + + #[test] + fn absorb_test() { + let mut rng = test_rng(); + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + + let params = get_bls12377_fq_params(); + let mut native_sponge = PoseidonTranscript::new(¶ms); + let mut rng = ark_std::test_rng(); + //let point = ark_bls12_377::G1Affine::rand(&mut rng); + let a = ark_ec::bls12::G1Prepared::default(); + let b = ark_ec::bls12::G2Prepared::default(); + let gt = ark_bls12_377::Bls12_377::pairing(a, b); + + + println!("GT "); + println!("{:?}", gt); + + native_sponge.append(b"U", >); + + let hash = native_sponge.challenge_scalar::(b"random_point"); + + println!("HASH: "); + println!("{:?}", hash); + + let circuit: TestudoCommVerifier = TestudoCommVerifier { + gt, + poseidon_params: get_bls12377_fq_params(), + _iv: PhantomData, + }; + + circuit.generate_constraints(cs.clone()).unwrap(); + assert!(cs.is_satisfied().unwrap()); + } +} + + // use crate::parameters::params_to_base_field; // use crate::poseidon_transcript::PoseidonTranscript; // use ark_bls12_377::constraints::G1Var; diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 1681d4a9..0c3e447f 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -1,649 +1,650 @@ -#![allow(clippy::too_many_arguments)] -use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; -use super::errors::ProofVerifyError; -use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; -use crate::math::Math; -use crate::mipp::MippProof; -use crate::poseidon_transcript::PoseidonTranscript; -use crate::sqrt_pst::Polynomial; -use crate::sumcheck::SumcheckInstanceProof; -use crate::transcript::Transcript; -use crate::unipoly::UniPoly; -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use ark_ec::pairing::Pairing; - -use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; -use itertools::Itertools; - -use super::r1csinstance::R1CSInstance; - -use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; -use super::timer::Timer; -use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; - -use crate::ark_std::UniformRand; -use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; - -use ark_serialize::*; -use ark_std::{One, Zero}; - -#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] -pub struct R1CSProof { - // The PST commitment to the multilinear extension of the witness. - pub comm: Commitment, - sc_proof_phase1: SumcheckInstanceProof, - claims_phase2: ( - E::ScalarField, - E::ScalarField, - E::ScalarField, - E::ScalarField, - ), - sc_proof_phase2: SumcheckInstanceProof, - pub eval_vars_at_ry: E::ScalarField, - pub proof_eval_vars_at_ry: Proof, - rx: Vec, - ry: Vec, - // The transcript state after the satisfiability proof was computed. - pub transcript_sat_state: E::ScalarField, - pub initial_state: E::ScalarField, - pub t: E::TargetField, - pub mipp_proof: MippProof, -} - -#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] -pub struct R1CSVerifierProof { - pub comm: Commitment, - pub circuit_proof: ark_groth16::Proof, - pub initial_state: E::ScalarField, - pub transcript_sat_state: E::ScalarField, - pub eval_vars_at_ry: E::ScalarField, - pub proof_eval_vars_at_ry: Proof, - pub t: E::TargetField, - pub mipp_proof: MippProof, -} - -#[derive(Clone)] -pub struct CircuitGens { - pk: ProvingKey, - pub vk: VerifyingKey, -} - -impl CircuitGens -where - E: Pairing, -{ - // Performs the circuit-specific setup required by Groth16 for the sumcheck - // circuit. This is done by filling the struct with dummy elements, ensuring - // the sizes are correct so the setup matches the circuit that will be proved. - pub fn setup( - num_cons: usize, - num_vars: usize, - num_inputs: usize, - poseidon: PoseidonConfig, - ) -> Self { - let mut rng = rand::thread_rng(); - - let uni_polys_round1 = (0..num_cons.log_2()) - .map(|_i| { - UniPoly::::from_evals(&[ - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - ]) - }) - .collect::>>(); - - let uni_polys_round2 = (0..num_vars.log_2() + 1) - .map(|_i| { - UniPoly::::from_evals(&[ - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - ]) - }) - .collect::>>(); - - let circuit = R1CSVerificationCircuit { - num_vars: num_vars, - num_cons: num_cons, - input: (0..num_inputs) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - input_as_sparse_poly: SparsePolynomial::new( - num_vars.log_2(), - (0..num_inputs + 1) - .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) - .collect::>>(), - ), - evals: ( - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - ), - params: poseidon, - prev_challenge: E::ScalarField::zero(), - claims_phase2: ( - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - ), - eval_vars_at_ry: E::ScalarField::zero(), - sc_phase1: SumcheckVerificationCircuit { - polys: uni_polys_round1, - }, - sc_phase2: SumcheckVerificationCircuit { - polys: uni_polys_round2, - }, - claimed_rx: (0..num_cons.log_2()) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - claimed_ry: (0..num_vars.log_2() + 1) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - claimed_transcript_sat_state: E::ScalarField::zero(), - }; - let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); - CircuitGens { pk, vk } - } -} - -#[derive(Clone)] -pub struct R1CSGens { - pub gens_pc: PolyCommitmentGens, - pub gens_gc: CircuitGens, -} - -impl R1CSGens { - // Performs the setup for the polynomial commitment PST and for Groth16. - pub fn setup( - label: &'static [u8], - num_cons: usize, - num_vars: usize, - num_inputs: usize, - poseidon: PoseidonConfig, - ) -> Self { - let num_poly_vars = num_vars.log_2(); - let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); - let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); - R1CSGens { gens_pc, gens_gc } - } -} - -impl R1CSProof -where - E: Pairing, - E::ScalarField: Absorb, -{ - fn prove_phase_one( - num_rounds: usize, - evals_tau: &mut DensePolynomial, - evals_Az: &mut DensePolynomial, - evals_Bz: &mut DensePolynomial, - evals_Cz: &mut DensePolynomial, - transcript: &mut PoseidonTranscript, - ) -> ( - SumcheckInstanceProof, - Vec, - Vec, - ) { - let comb_func = - |poly_tau_comp: &E::ScalarField, - poly_A_comp: &E::ScalarField, - poly_B_comp: &E::ScalarField, - poly_C_comp: &E::ScalarField| - -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; - - let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term( - &E::ScalarField::zero(), // claim is zero - num_rounds, - evals_tau, - evals_Az, - evals_Bz, - evals_Cz, - comb_func, - transcript, - ); - - (sc_proof_phase_one, r, claims) - } - - fn prove_phase_two( - num_rounds: usize, - claim: &E::ScalarField, - evals_z: &mut DensePolynomial, - evals_ABC: &mut DensePolynomial, - transcript: &mut PoseidonTranscript, - ) -> ( - SumcheckInstanceProof, - Vec, - Vec, - ) { - let comb_func = |poly_A_comp: &E::ScalarField, - poly_B_comp: &E::ScalarField| - -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; - let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad( - claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, - ); - - (sc_proof_phase_two, r, claims) - } - - // Proves the R1CS instance inst is satisfiable given the assignment - // vars. - pub fn prove( - inst: &R1CSInstance, - vars: Vec, - input: &[E::ScalarField], - gens: &R1CSGens, - transcript: &mut PoseidonTranscript, - ) -> (Self, Vec, Vec) { - let timer_prove = Timer::new("R1CSProof::prove"); - // we currently require the number of |inputs| + 1 to be at most number of vars - assert!(input.len() < vars.len()); - - // create the multilinear witness polynomial from the satisfying assiment - // expressed as the list of sqrt-sized polynomials - let mut pl = Polynomial::from_evaluations(&vars.clone()); - - let timer_commit = Timer::new("polycommit"); - - // commitment list to the satisfying witness polynomial list - let (comm_list, t) = pl.commit(&gens.gens_pc.ck); - - transcript.append_gt::(b"", &t); - - timer_commit.stop(); - - let initial_state = transcript.challenge_scalar(b""); - transcript.new_from_state(&initial_state); - - transcript.append_scalar_vector(b"", &input); - - let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); - - // append input to variables to create a single vector z - let z = { - let num_inputs = input.len(); - let num_vars = vars.len(); - let mut z = vars; - z.extend(&vec![E::ScalarField::one()]); // add constant term in z - z.extend(input); - z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros - z - }; - - // derive the verifier's challenge tau - let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); - let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); - // compute the initial evaluation table for R(\tau, x) - let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); - let (mut poly_Az, mut poly_Bz, mut poly_Cz) = - inst.multiply_vec(inst.get_num_cons(), z.len(), &z); - - let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( - num_rounds_x, - &mut poly_tau, - &mut poly_Az, - &mut poly_Bz, - &mut poly_Cz, - transcript, - ); - assert_eq!(poly_tau.len(), 1); - assert_eq!(poly_Az.len(), 1); - assert_eq!(poly_Bz.len(), 1); - assert_eq!(poly_Cz.len(), 1); - timer_sc_proof_phase1.stop(); - - let (tau_claim, Az_claim, Bz_claim, Cz_claim) = - (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); - let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; - - // prove the final step of sum-check #1 - let taus_bound_rx = tau_claim; - let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; - - let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); - // combine the three claims into a single claim - let r_A: E::ScalarField = transcript.challenge_scalar(b""); - let r_B: E::ScalarField = transcript.challenge_scalar(b""); - let r_C: E::ScalarField = transcript.challenge_scalar(b""); - let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; - - let evals_ABC = { - // compute the initial evaluation table for R(\tau, x) - let evals_rx = EqPolynomial::new(rx.clone()).evals(); - let (evals_A, evals_B, evals_C) = - inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); - - assert_eq!(evals_A.len(), evals_B.len()); - assert_eq!(evals_A.len(), evals_C.len()); - (0..evals_A.len()) - .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) - .collect::>() - }; - - // another instance of the sum-check protocol - let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( - num_rounds_y, - &claim_phase2, - &mut DensePolynomial::new(z), - &mut DensePolynomial::new(evals_ABC), - transcript, - ); - timer_sc_proof_phase2.stop(); - let transcript_sat_state = transcript.challenge_scalar(b""); - transcript.new_from_state(&transcript_sat_state); - - let timmer_opening = Timer::new("polyopening"); - - let (comm, proof_eval_vars_at_ry, mipp_proof) = - pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); - - timmer_opening.stop(); - - let timer_polyeval = Timer::new("polyeval"); - let eval_vars_at_ry = pl.eval(&ry[1..]); - timer_polyeval.stop(); - timer_prove.stop(); - ( - R1CSProof { - comm, - initial_state, - sc_proof_phase1, - claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), - sc_proof_phase2, - eval_vars_at_ry, - proof_eval_vars_at_ry, - rx: rx.clone(), - ry: ry.clone(), - transcript_sat_state, - t, - mipp_proof, - }, - rx, - ry, - ) - } - - // Creates a Groth16 proof for the verification of sumcheck, expressed - // as a circuit. - pub fn prove_verifier( - &self, - num_vars: usize, - num_cons: usize, - input: &[E::ScalarField], - evals: &(E::ScalarField, E::ScalarField, E::ScalarField), - transcript: &mut PoseidonTranscript, - gens: &R1CSGens, - poseidon: PoseidonConfig, - ) -> Result, ProofVerifyError> { - // serialise and add the IPP commitment to the transcript - transcript.append_gt::(b"", &self.t); - - let initial_state = transcript.challenge_scalar(b""); - transcript.new_from_state(&initial_state); - - let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; - //remaining inputs - input_as_sparse_poly_entries.extend( - (0..input.len()) - .map(|i| SparsePolyEntry::new(i + 1, input[i])) - .collect::>>(), - ); - let input_as_sparse_poly = - SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); - - let config = VerifierConfig { - num_vars, - num_cons, - input: input.to_vec(), - evals: *evals, - params: poseidon, - prev_challenge: initial_state, - claims_phase2: self.claims_phase2, - polys_sc1: self.sc_proof_phase1.polys.clone(), - polys_sc2: self.sc_proof_phase2.polys.clone(), - eval_vars_at_ry: self.eval_vars_at_ry, - input_as_sparse_poly, - comm: self.comm.clone(), - rx: self.rx.clone(), - ry: self.ry.clone(), - transcript_sat_state: self.transcript_sat_state, - }; - - let circuit = R1CSVerificationCircuit::new(&config); - - let circuit_prover_timer = Timer::new("provecircuit"); - let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); - circuit_prover_timer.stop(); - - Ok(R1CSVerifierProof { - comm: self.comm.clone(), - circuit_proof: proof, - initial_state: self.initial_state, - transcript_sat_state: self.transcript_sat_state, - eval_vars_at_ry: self.eval_vars_at_ry, - proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), - t: self.t, - mipp_proof: self.mipp_proof.clone(), - }) - } -} - -impl R1CSVerifierProof -where - ::ScalarField: Absorb, -{ - // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial - // commitment opening. - pub fn verify( - &self, - r: (Vec, Vec), - input: &[E::ScalarField], - evals: &(E::ScalarField, E::ScalarField, E::ScalarField), - transcript: &mut PoseidonTranscript, - gens: &R1CSGens, - ) -> Result { - let (rx, ry) = &r; - let (Ar, Br, Cr) = evals; - let mut pubs = vec![self.initial_state]; - pubs.extend(input.clone()); - pubs.extend(rx.clone()); - pubs.extend(ry.clone()); - pubs.extend(vec![ - self.eval_vars_at_ry, - *Ar, - *Br, - *Cr, - self.transcript_sat_state, - ]); - transcript.new_from_state(&self.transcript_sat_state); - par! { - // verifies the Groth16 proof for the spartan verifier - let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(), - - // verifies the proof of opening against the result of evaluating the - // witness polynomial at point ry - let res = Polynomial::verify( - transcript, - &gens.gens_pc.vk, - &self.comm, - &ry[1..], - self.eval_vars_at_ry, - &self.proof_eval_vars_at_ry, - &self.mipp_proof, - &self.t, - ) - }; - assert!(is_verified == true); - assert!(res == true); - Ok(is_verified && res) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use ark_ec::CurveGroup; - use ark_ff::Field; -use ark_r1cs_std::pairing::PairingVar; - use crate::verifier_circuit::VerifierCircuit; - type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; - use ark_ff::PrimeField; - use ark_std::UniformRand; - use ark_relations::r1cs::ConstraintSystem; - type F = ark_bls12_377::Fr; - use crate::rand::SeedableRng; - use ark_relations::r1cs::ConstraintSynthesizer; +// #![allow(clippy::too_many_arguments)] +// use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; +// use super::errors::ProofVerifyError; +// use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; +// use crate::math::Math; +// use crate::mipp::MippProof; +// use crate::poseidon_transcript::PoseidonTranscript; +// use crate::sqrt_pst::Polynomial; +// use crate::sumcheck::SumcheckInstanceProof; +// use crate::transcript::Transcript; +// use crate::unipoly::UniPoly; +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; + +// use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; +// use itertools::Itertools; + +// use super::r1csinstance::R1CSInstance; + +// use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; +// use super::timer::Timer; +// use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; + +// use crate::ark_std::UniformRand; +// use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; + +// use ark_serialize::*; +// use ark_std::{One, Zero}; + +// #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] +// pub struct R1CSProof { +// // The PST commitment to the multilinear extension of the witness. +// pub comm: Commitment, +// sc_proof_phase1: SumcheckInstanceProof, +// claims_phase2: ( +// E::ScalarField, +// E::ScalarField, +// E::ScalarField, +// E::ScalarField, +// ), +// sc_proof_phase2: SumcheckInstanceProof, +// pub eval_vars_at_ry: E::ScalarField, +// pub proof_eval_vars_at_ry: Proof, +// rx: Vec, +// ry: Vec, +// // The transcript state after the satisfiability proof was computed. +// pub transcript_sat_state: E::ScalarField, +// pub initial_state: E::ScalarField, +// pub t: E::TargetField, +// pub mipp_proof: MippProof, +// } + +// #[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] +// pub struct R1CSVerifierProof { +// pub comm: Commitment, +// pub circuit_proof: ark_groth16::Proof, +// pub initial_state: E::ScalarField, +// pub transcript_sat_state: E::ScalarField, +// pub eval_vars_at_ry: E::ScalarField, +// pub proof_eval_vars_at_ry: Proof, +// pub t: E::TargetField, +// pub mipp_proof: MippProof, +// } + +// #[derive(Clone)] +// pub struct CircuitGens { +// pk: ProvingKey, +// pub vk: VerifyingKey, +// } + +// impl CircuitGens +// where +// E: Pairing, +// { +// // Performs the circuit-specific setup required by Groth16 for the sumcheck +// // circuit. This is done by filling the struct with dummy elements, ensuring +// // the sizes are correct so the setup matches the circuit that will be proved. +// pub fn setup( +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// let mut rng = rand::thread_rng(); + +// let uni_polys_round1 = (0..num_cons.log_2()) +// .map(|_i| { +// UniPoly::::from_evals(&[ +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// ]) +// }) +// .collect::>>(); + +// let uni_polys_round2 = (0..num_vars.log_2() + 1) +// .map(|_i| { +// UniPoly::::from_evals(&[ +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// ]) +// }) +// .collect::>>(); + +// let circuit = R1CSVerificationCircuit { +// num_vars: num_vars, +// num_cons: num_cons, +// input: (0..num_inputs) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// input_as_sparse_poly: SparsePolynomial::new( +// num_vars.log_2(), +// (0..num_inputs + 1) +// .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) +// .collect::>>(), +// ), +// evals: ( +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// ), +// params: poseidon, +// prev_challenge: E::ScalarField::zero(), +// claims_phase2: ( +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// ), +// eval_vars_at_ry: E::ScalarField::zero(), +// sc_phase1: SumcheckVerificationCircuit { +// polys: uni_polys_round1, +// }, +// sc_phase2: SumcheckVerificationCircuit { +// polys: uni_polys_round2, +// }, +// claimed_rx: (0..num_cons.log_2()) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// claimed_ry: (0..num_vars.log_2() + 1) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// claimed_transcript_sat_state: E::ScalarField::zero(), +// }; +// let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); +// CircuitGens { pk, vk } +// } +// } + +// #[derive(Clone)] +// pub struct R1CSGens { +// pub gens_pc: PolyCommitmentGens, +// pub gens_gc: CircuitGens, +// } + +// impl R1CSGens { +// // Performs the setup for the polynomial commitment PST and for Groth16. +// pub fn setup( +// label: &'static [u8], +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// let num_poly_vars = num_vars.log_2(); +// let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); +// let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); +// R1CSGens { gens_pc, gens_gc } +// } +// } + +// impl R1CSProof +// where +// E: Pairing, +// E::ScalarField: Absorb, +// { +// fn prove_phase_one( +// num_rounds: usize, +// evals_tau: &mut DensePolynomial, +// evals_Az: &mut DensePolynomial, +// evals_Bz: &mut DensePolynomial, +// evals_Cz: &mut DensePolynomial, +// transcript: &mut PoseidonTranscript, +// ) -> ( +// SumcheckInstanceProof, +// Vec, +// Vec, +// ) { +// let comb_func = +// |poly_tau_comp: &E::ScalarField, +// poly_A_comp: &E::ScalarField, +// poly_B_comp: &E::ScalarField, +// poly_C_comp: &E::ScalarField| +// -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; + +// let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term( +// &E::ScalarField::zero(), // claim is zero +// num_rounds, +// evals_tau, +// evals_Az, +// evals_Bz, +// evals_Cz, +// comb_func, +// transcript, +// ); + +// (sc_proof_phase_one, r, claims) +// } + +// fn prove_phase_two( +// num_rounds: usize, +// claim: &E::ScalarField, +// evals_z: &mut DensePolynomial, +// evals_ABC: &mut DensePolynomial, +// transcript: &mut PoseidonTranscript, +// ) -> ( +// SumcheckInstanceProof, +// Vec, +// Vec, +// ) { +// let comb_func = |poly_A_comp: &E::ScalarField, +// poly_B_comp: &E::ScalarField| +// -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; +// let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad( +// claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, +// ); + +// (sc_proof_phase_two, r, claims) +// } + +// // Proves the R1CS instance inst is satisfiable given the assignment +// // vars. +// pub fn prove( +// inst: &R1CSInstance, +// vars: Vec, +// input: &[E::ScalarField], +// gens: &R1CSGens, +// transcript: &mut PoseidonTranscript, +// ) -> (Self, Vec, Vec) { +// let timer_prove = Timer::new("R1CSProof::prove"); +// // we currently require the number of |inputs| + 1 to be at most number of vars +// assert!(input.len() < vars.len()); + +// // create the multilinear witness polynomial from the satisfying assiment +// // expressed as the list of sqrt-sized polynomials +// let mut pl = Polynomial::from_evaluations(&vars.clone()); + +// let timer_commit = Timer::new("polycommit"); + +// // commitment list to the satisfying witness polynomial list +// let (comm_list, t) = pl.commit(&gens.gens_pc.ck); + +// transcript.append_gt::(b"", &t); + +// timer_commit.stop(); + +// let initial_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&initial_state); + +// transcript.append_scalar_vector(b"", &input); + +// let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); + +// // append input to variables to create a single vector z +// let z = { +// let num_inputs = input.len(); +// let num_vars = vars.len(); +// let mut z = vars; +// z.extend(&vec![E::ScalarField::one()]); // add constant term in z +// z.extend(input); +// z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros +// z +// }; + +// // derive the verifier's challenge tau +// let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); +// let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); +// // compute the initial evaluation table for R(\tau, x) +// let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); +// let (mut poly_Az, mut poly_Bz, mut poly_Cz) = +// inst.multiply_vec(inst.get_num_cons(), z.len(), &z); + +// let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( +// num_rounds_x, +// &mut poly_tau, +// &mut poly_Az, +// &mut poly_Bz, +// &mut poly_Cz, +// transcript, +// ); +// assert_eq!(poly_tau.len(), 1); +// assert_eq!(poly_Az.len(), 1); +// assert_eq!(poly_Bz.len(), 1); +// assert_eq!(poly_Cz.len(), 1); +// timer_sc_proof_phase1.stop(); + +// let (tau_claim, Az_claim, Bz_claim, Cz_claim) = +// (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); +// let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; + +// // prove the final step of sum-check #1 +// let taus_bound_rx = tau_claim; +// let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; + +// let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); +// // combine the three claims into a single claim +// let r_A: E::ScalarField = transcript.challenge_scalar(b""); +// let r_B: E::ScalarField = transcript.challenge_scalar(b""); +// let r_C: E::ScalarField = transcript.challenge_scalar(b""); +// let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; + +// let evals_ABC = { +// // compute the initial evaluation table for R(\tau, x) +// let evals_rx = EqPolynomial::new(rx.clone()).evals(); +// let (evals_A, evals_B, evals_C) = +// inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); + +// assert_eq!(evals_A.len(), evals_B.len()); +// assert_eq!(evals_A.len(), evals_C.len()); +// (0..evals_A.len()) +// .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) +// .collect::>() +// }; + +// // another instance of the sum-check protocol +// let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( +// num_rounds_y, +// &claim_phase2, +// &mut DensePolynomial::new(z), +// &mut DensePolynomial::new(evals_ABC), +// transcript, +// ); +// timer_sc_proof_phase2.stop(); +// let transcript_sat_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&transcript_sat_state); + +// let timmer_opening = Timer::new("polyopening"); + +// let (comm, proof_eval_vars_at_ry, mipp_proof) = +// pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); + +// timmer_opening.stop(); + +// let timer_polyeval = Timer::new("polyeval"); +// let eval_vars_at_ry = pl.eval(&ry[1..]); +// timer_polyeval.stop(); +// timer_prove.stop(); +// ( +// R1CSProof { +// comm, +// initial_state, +// sc_proof_phase1, +// claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), +// sc_proof_phase2, +// eval_vars_at_ry, +// proof_eval_vars_at_ry, +// rx: rx.clone(), +// ry: ry.clone(), +// transcript_sat_state, +// t, +// mipp_proof, +// }, +// rx, +// ry, +// ) +// } + +// // Creates a Groth16 proof for the verification of sumcheck, expressed +// // as a circuit. +// pub fn prove_verifier( +// &self, +// num_vars: usize, +// num_cons: usize, +// input: &[E::ScalarField], +// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), +// transcript: &mut PoseidonTranscript, +// gens: &R1CSGens, +// poseidon: PoseidonConfig, +// ) -> Result, ProofVerifyError> { +// // serialise and add the IPP commitment to the transcript +// transcript.append_gt::(b"", &self.t); + +// let initial_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&initial_state); + +// let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; +// //remaining inputs +// input_as_sparse_poly_entries.extend( +// (0..input.len()) +// .map(|i| SparsePolyEntry::new(i + 1, input[i])) +// .collect::>>(), +// ); +// let input_as_sparse_poly = +// SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); + +// let config = VerifierConfig { +// num_vars, +// num_cons, +// input: input.to_vec(), +// evals: *evals, +// params: poseidon, +// prev_challenge: initial_state, +// claims_phase2: self.claims_phase2, +// polys_sc1: self.sc_proof_phase1.polys.clone(), +// polys_sc2: self.sc_proof_phase2.polys.clone(), +// eval_vars_at_ry: self.eval_vars_at_ry, +// input_as_sparse_poly, +// comm: self.comm.clone(), +// rx: self.rx.clone(), +// ry: self.ry.clone(), +// transcript_sat_state: self.transcript_sat_state, +// }; + +// let circuit = R1CSVerificationCircuit::new(&config); + +// let circuit_prover_timer = Timer::new("provecircuit"); +// let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); +// circuit_prover_timer.stop(); + +// Ok(R1CSVerifierProof { +// comm: self.comm.clone(), +// circuit_proof: proof, +// initial_state: self.initial_state, +// transcript_sat_state: self.transcript_sat_state, +// eval_vars_at_ry: self.eval_vars_at_ry, +// proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), +// t: self.t, +// mipp_proof: self.mipp_proof.clone(), +// }) +// } +// } + +// impl R1CSVerifierProof +// where +// ::ScalarField: Absorb, +// { +// // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial +// // commitment opening. +// pub fn verify( +// &self, +// r: (Vec, Vec), +// input: &[E::ScalarField], +// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), +// transcript: &mut PoseidonTranscript, +// gens: &R1CSGens, +// ) -> Result { +// let (rx, ry) = &r; +// let (Ar, Br, Cr) = evals; +// let mut pubs = vec![self.initial_state]; +// pubs.extend(input.clone()); +// pubs.extend(rx.clone()); +// pubs.extend(ry.clone()); +// pubs.extend(vec![ +// self.eval_vars_at_ry, +// *Ar, +// *Br, +// *Cr, +// self.transcript_sat_state, +// ]); +// transcript.new_from_state(&self.transcript_sat_state); +// // par! { +// // verifies the Groth16 proof for the spartan verifier +// let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(); + +// // verifies the proof of opening against the result of evaluating the +// // witness polynomial at point ry +// // let res = Polynomial::verify( +// // transcript, +// // &gens.gens_pc.vk, +// // &self.comm, +// // &ry[1..], +// // self.eval_vars_at_ry, +// // &self.proof_eval_vars_at_ry, +// // &self.mipp_proof, +// // &self.t, +// // ) +// //}; +// // assert!(is_verified == true); +// //assert!(res == true); +// // Ok(is_verified && res) +// Ok(true) +// } +// } + +// #[cfg(test)] +// mod tests { + +// use super::*; +// use ark_ec::CurveGroup; +// use ark_ff::Field; +// use ark_r1cs_std::pairing::PairingVar; +// // use crate::verifier_circuit::VerifierCircuit; +// type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; +// use ark_ff::PrimeField; +// use ark_std::UniformRand; +// use ark_relations::r1cs::ConstraintSystem; +// type F = ark_bls12_377::Fr; +// use crate::rand::SeedableRng; +// use ark_relations::r1cs::ConstraintSynthesizer; - fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { - // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 - // rounded to the nearest power of two - let num_cons = 128; - let num_vars = 256; - let num_inputs = 2; - - // encode the above constraints into three matrices - let mut A: Vec<(usize, usize, F)> = Vec::new(); - let mut B: Vec<(usize, usize, F)> = Vec::new(); - let mut C: Vec<(usize, usize, F)> = Vec::new(); - - let one = F::one(); - // constraint 0 entries - // (Z1 + Z2) * I0 - Z3 = 0; - A.push((0, 0, one)); - A.push((0, 1, one)); - B.push((0, num_vars + 1, one)); - C.push((0, 2, one)); - - // constraint 1 entries - // (Z1 + I1) * (Z3) - Z4 = 0 - A.push((1, 0, one)); - A.push((1, num_vars + 2, one)); - B.push((1, 2, one)); - C.push((1, 3, one)); - // constraint 3 entries - // Z5 * 1 - 0 = 0 - A.push((2, 4, one)); - B.push((2, num_vars, one)); - - let inst = R1CSInstance::new(num_cons, num_vars, num_inputs, &A, &B, &C); - - // compute a satisfying assignment - let mut rng = ark_std::rand::thread_rng(); - let i0 = F::rand(&mut rng); - let i1 = F::rand(&mut rng); - let z1 = F::rand(&mut rng); - let z2 = F::rand(&mut rng); - let z3 = (z1 + z2) * i0; // constraint 1: (Z1 + Z2) * I0 - Z3 = 0; - let z4 = (z1 + i1) * z3; // constraint 2: (Z1 + I1) * (Z3) - Z4 = 0 - let z5 = F::zero(); //constraint 3 - - let mut vars = vec![F::zero(); num_vars]; - vars[0] = z1; - vars[1] = z2; - vars[2] = z3; - vars[3] = z4; - vars[4] = z5; - - let mut input = vec![F::zero(); num_inputs]; - input[0] = i0; - input[1] = i1; - - (inst, vars, input) - } - - #[test] - fn test_tiny_r1cs() { - let (inst, vars, input) = tests::produce_tiny_r1cs(); - let is_sat = inst.is_sat(&vars, &input); - assert!(is_sat); - } - - #[test] - fn test_synthetic_r1cs() { - type F = ark_bls12_377::Fr; - let (inst, vars, input) = R1CSInstance::::produce_synthetic_r1cs(1024, 1024, 10); - let is_sat = inst.is_sat(&vars, &input); - assert!(is_sat); - } - - use crate::parameters::PoseidonConfiguration; - //#[test] - // fn check_r1cs_proof_ark_blst() { - // let params = ark_blst::Scalar::poseidon_params(); - // check_r1cs_proof::(params); - // } - #[test] - fn check_r1cs_proof_bls12_377() { - let params = ark_bls12_377::Fr::poseidon_params(); - check_r1cs_proof::(params); - } - - //#[test] - // fn check_r1cs_proof_bls12_381() { - // let params = ark_bls12_381::Fr::poseidon_params(); - // check_r1cs_proof::(params); - // } - fn check_r1cs_proof(params: PoseidonConfig) - where - P: Pairing, - IV: PairingVar>, - P::ScalarField: PrimeField, - P::ScalarField: Absorb, - { - let num_vars = 1024; - let num_cons = num_vars; - let num_inputs = 3; - let (inst, vars, input) = - R1CSInstance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - let gens = R1CSGens::

::setup(b"test-m", num_cons, num_vars, num_inputs, params.clone()); - - //let params = poseidon_params(); - // let mut random_tape = RandomTape::new(b"proof"); - - let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); - let c = prover_transcript.challenge_scalar::(b""); - prover_transcript.new_from_state(&c); - let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); - - let inst_evals = inst.evaluate(&rx, &ry); - - prover_transcript.new_from_state(&c); - let verifer_proof = proof - .prove_verifier( - num_vars, - num_cons, - &input, - &inst_evals, - &mut prover_transcript, - &gens, - params.clone(), - ) - .unwrap(); - - let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); - // assert!(verifer_proof - // .verify( - // (rx, ry), - // &input, - // &inst_evals, - // &mut verifier_transcript, - // &gens - // ) - // .is_ok()); - let mut rng = rand_chacha::ChaChaRng::seed_from_u64(1776); - let cs = ConstraintSystem::>::new_ref(); - let circuit = VerifierCircuit::::new((rx, ry),input,inst_evals,verifier_transcript,gens,verifer_proof).unwrap(); - circuit.generate_constraints(cs.clone()); - // .unwrap(); - assert!(cs.is_satisfied().unwrap()); - - - } -} \ No newline at end of file +// fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { +// // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 +// // rounded to the nearest power of two +// let num_cons = 128; +// let num_vars = 256; +// let num_inputs = 2; + +// // encode the above constraints into three matrices +// let mut A: Vec<(usize, usize, F)> = Vec::new(); +// let mut B: Vec<(usize, usize, F)> = Vec::new(); +// let mut C: Vec<(usize, usize, F)> = Vec::new(); + +// let one = F::one(); +// // constraint 0 entries +// // (Z1 + Z2) * I0 - Z3 = 0; +// A.push((0, 0, one)); +// A.push((0, 1, one)); +// B.push((0, num_vars + 1, one)); +// C.push((0, 2, one)); + +// // constraint 1 entries +// // (Z1 + I1) * (Z3) - Z4 = 0 +// A.push((1, 0, one)); +// A.push((1, num_vars + 2, one)); +// B.push((1, 2, one)); +// C.push((1, 3, one)); +// // constraint 3 entries +// // Z5 * 1 - 0 = 0 +// A.push((2, 4, one)); +// B.push((2, num_vars, one)); + +// let inst = R1CSInstance::new(num_cons, num_vars, num_inputs, &A, &B, &C); + +// // compute a satisfying assignment +// let mut rng = ark_std::rand::thread_rng(); +// let i0 = F::rand(&mut rng); +// let i1 = F::rand(&mut rng); +// let z1 = F::rand(&mut rng); +// let z2 = F::rand(&mut rng); +// let z3 = (z1 + z2) * i0; // constraint 1: (Z1 + Z2) * I0 - Z3 = 0; +// let z4 = (z1 + i1) * z3; // constraint 2: (Z1 + I1) * (Z3) - Z4 = 0 +// let z5 = F::zero(); //constraint 3 + +// let mut vars = vec![F::zero(); num_vars]; +// vars[0] = z1; +// vars[1] = z2; +// vars[2] = z3; +// vars[3] = z4; +// vars[4] = z5; + +// let mut input = vec![F::zero(); num_inputs]; +// input[0] = i0; +// input[1] = i1; + +// (inst, vars, input) +// } + +// #[test] +// fn test_tiny_r1cs() { +// let (inst, vars, input) = tests::produce_tiny_r1cs(); +// let is_sat = inst.is_sat(&vars, &input); +// assert!(is_sat); +// } + +// #[test] +// fn test_synthetic_r1cs() { +// type F = ark_bls12_377::Fr; +// let (inst, vars, input) = R1CSInstance::::produce_synthetic_r1cs(1024, 1024, 10); +// let is_sat = inst.is_sat(&vars, &input); +// assert!(is_sat); +// } + +// use crate::parameters::PoseidonConfiguration; +// //#[test] +// // fn check_r1cs_proof_ark_blst() { +// // let params = ark_blst::Scalar::poseidon_params(); +// // check_r1cs_proof::(params); +// // } +// #[test] +// fn check_r1cs_proof_bls12_377() { +// let params = ark_bls12_377::Fr::poseidon_params(); +// check_r1cs_proof::(params); +// } + +// //#[test +// // fn check_r1cs_proof_bls12_381() { +// // let params = ark_bls12_381::Fr::poseidon_params(); +// // check_r1cs_proof::(params); +// // } +// fn check_r1cs_proof(params: PoseidonConfig) +// where +// P: Pairing, +// IV: PairingVar>, +// P::ScalarField: PrimeField, +// P::ScalarField: Absorb, +// { +// let num_vars = 1024; +// let num_cons = num_vars; +// let num_inputs = 3; +// let (inst, vars, input) = +// R1CSInstance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + +// let gens = R1CSGens::

::setup(b"test-m", num_cons, num_vars, num_inputs, params.clone()); + +// //let params = poseidon_params(); +// // let mut random_tape = RandomTape::new(b"proof"); + +// let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); +// let c = prover_transcript.challenge_scalar::(b""); +// prover_transcript.new_from_state(&c); +// let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); + +// let inst_evals = inst.evaluate(&rx, &ry); + +// prover_transcript.new_from_state(&c); +// let verifer_proof = proof +// .prove_verifier( +// num_vars, +// num_cons, +// &input, +// &inst_evals, +// &mut prover_transcript, +// &gens, +// params.clone(), +// ) +// .unwrap(); + +// let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); +// // assert!(verifer_proof +// // .verify( +// // (rx, ry), +// // &input, +// // &inst_evals, +// // &mut verifier_transcript, +// // &gens +// // ) +// // .is_ok()); +// // let mut rng = rand_chacha::ChaChaRng::seed_from_u64(1776); +// // let cs = ConstraintSystem::>::new_ref(); +// // let circuit = VerifierCircuit::::new((rx, ry),input,inst_evals,verifier_transcript,gens,verifer_proof).unwrap(); +// // circuit.generate_constraints(cs.clone()); +// // // .unwrap(); +// // assert!(cs.is_satisfied().unwrap()); + + +// } +// } \ No newline at end of file diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index e4aec374..81adc87f 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -167,7 +167,7 @@ impl Polynomial { pub fn open( &mut self, - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, comm_list: Vec>, ck: &CommitterKey, point: &[E::ScalarField], @@ -230,7 +230,7 @@ impl Polynomial { } pub fn verify( - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, vk: &VerifierKey, U: &Commitment, point: &[E::ScalarField], @@ -267,7 +267,7 @@ impl Polynomial { #[cfg(test)] mod tests { - use crate::parameters::poseidon_params; + use crate::parameters::{poseidon_params, get_bls12377_fq_params}; use super::*; type F = ark_bls12_377::Fr; @@ -322,11 +322,11 @@ mod tests { let (comm_list, t) = pl.commit(&ck); let params = poseidon_params(); - let mut prover_transcript = PoseidonTranscript::new(¶ms); + let mut prover_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let mut verifier_transcript = PoseidonTranscript::new(¶ms); + let mut verifier_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); let res = Polynomial::verify( &mut verifier_transcript, diff --git a/src/testudo_nizk.rs b/src/testudo_nizk.rs index a456a603..b408804a 100644 --- a/src/testudo_nizk.rs +++ b/src/testudo_nizk.rs @@ -1,202 +1,202 @@ -use std::cmp::max; - -use crate::errors::ProofVerifyError; -use crate::r1csproof::R1CSVerifierProof; -use crate::{ - poseidon_transcript::PoseidonTranscript, - r1csproof::{R1CSGens, R1CSProof}, - transcript::Transcript, - InputsAssignment, Instance, VarsAssignment, -}; -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use ark_ec::pairing::Pairing; - -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - -#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] - -// TestudoNizk is suitable for uniform circuits where the -// evaluation of R1CS matrices A, B and C is cheap and can -// be done by the verifier. For more complex circuits this -// operation has to be offloaded to the prover. -pub struct TestudoNizk { - pub r1cs_verifier_proof: R1CSVerifierProof, - pub r: (Vec, Vec), -} - -pub struct TestudoNizkGens { - gens_r1cs_sat: R1CSGens, -} - -impl TestudoNizkGens { - /// Performs the setup required by the polynomial commitment PST and Groth16 - pub fn setup( - num_cons: usize, - num_vars: usize, - num_inputs: usize, - poseidon: PoseidonConfig, - ) -> Self { - // ensure num_vars is a power of 2 - let num_vars_padded = { - let mut num_vars_padded = max(num_vars, num_inputs + 1); - if num_vars_padded != num_vars_padded.next_power_of_two() { - num_vars_padded = num_vars_padded.next_power_of_two(); - } - num_vars_padded - }; - - let num_cons_padded = { - let mut num_cons_padded = num_cons; - - // ensure that num_cons_padded is at least 2 - if num_cons_padded == 0 || num_cons_padded == 1 { - num_cons_padded = 2; - } - - // ensure that num_cons_padded is a power of 2 - if num_cons.next_power_of_two() != num_cons { - num_cons_padded = num_cons.next_power_of_two(); - } - num_cons_padded - }; - - let gens_r1cs_sat = R1CSGens::setup( - b"gens_r1cs_sat", - num_cons_padded, - num_vars_padded, - num_inputs, - poseidon, - ); - TestudoNizkGens { gens_r1cs_sat } - } -} - -impl TestudoNizk -where - E::ScalarField: Absorb, -{ - // Returns a proof that the R1CS instance is satisfiable - pub fn prove( - inst: &Instance, - vars: VarsAssignment, - inputs: &InputsAssignment, - gens: &TestudoNizkGens, - transcript: &mut PoseidonTranscript, - poseidon: PoseidonConfig, - ) -> Result, ProofVerifyError> { - transcript.append_bytes(b"", &inst.digest); - - let c: E::ScalarField = transcript.challenge_scalar(b""); - transcript.new_from_state(&c); - - // we might need to pad variables - let padded_vars = { - let num_padded_vars = inst.inst.get_num_vars(); - let num_vars = vars.assignment.len(); - if num_padded_vars > num_vars { - vars.pad(num_padded_vars) - } else { - vars - } - }; - - let (r1cs_sat_proof, rx, ry) = R1CSProof::prove( - &inst.inst, - padded_vars.assignment, - &inputs.assignment, - &gens.gens_r1cs_sat, - transcript, - ); - - let inst_evals = inst.inst.evaluate(&rx, &ry); - - transcript.new_from_state(&c); - let r1cs_verifier_proof = r1cs_sat_proof - .prove_verifier( - inst.inst.get_num_vars(), - inst.inst.get_num_cons(), - &inputs.assignment, - &inst_evals, - transcript, - &gens.gens_r1cs_sat, - poseidon, - ) - .unwrap(); - Ok(TestudoNizk { - r1cs_verifier_proof, - r: (rx, ry), - }) - } - - // Verifies the satisfiability proof for the R1CS instance. In NIZK mode, the - // verifier evaluates matrices A, B and C themselves, which is a linear - // operation and hence this is not a SNARK. - // However, for highly structured circuits this operation is fast. - pub fn verify( - &self, - gens: &TestudoNizkGens, - inst: &Instance, - input: &InputsAssignment, - transcript: &mut PoseidonTranscript, - _poseidon: PoseidonConfig, - ) -> Result { - transcript.append_bytes(b"", &inst.digest); - let (claimed_rx, claimed_ry) = &self.r; - let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry); - - let sat_verified = self.r1cs_verifier_proof.verify( - (claimed_rx.clone(), claimed_ry.clone()), - &input.assignment, - &inst_evals, - transcript, - &gens.gens_r1cs_sat, - )?; - assert!(sat_verified == true); - Ok(sat_verified) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - parameters::poseidon_params, - poseidon_transcript::PoseidonTranscript, - testudo_nizk::{TestudoNizk, TestudoNizkGens}, - Instance, - }; - - #[test] - pub fn check_testudo_nizk() { - let num_vars = 256; - let num_cons = num_vars; - let num_inputs = 10; - - type E = ark_bls12_377::Bls12_377; - - // produce public generators - let gens = TestudoNizkGens::::setup(num_cons, num_vars, num_inputs, poseidon_params()); - - // produce a synthetic R1CSInstance - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - let params = poseidon_params(); - - // produce a proof - let mut prover_transcript = PoseidonTranscript::new(¶ms); - let proof = - TestudoNizk::prove(&inst, vars, &inputs, &gens, &mut prover_transcript, params).unwrap(); - - // verify the proof - let mut verifier_transcript = PoseidonTranscript::new(&poseidon_params()); - assert!(proof - .verify( - &gens, - &inst, - &inputs, - &mut verifier_transcript, - poseidon_params() - ) - .is_ok()); - } -} +// use std::cmp::max; + +// use crate::errors::ProofVerifyError; +// use crate::r1csproof::R1CSVerifierProof; +// use crate::{ +// poseidon_transcript::PoseidonTranscript, +// r1csproof::{R1CSGens, R1CSProof}, +// transcript::Transcript, +// InputsAssignment, Instance, VarsAssignment, +// }; +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; + +// use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +// #[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] + +// // TestudoNizk is suitable for uniform circuits where the +// // evaluation of R1CS matrices A, B and C is cheap and can +// // be done by the verifier. For more complex circuits this +// // operation has to be offloaded to the prover. +// pub struct TestudoNizk { +// pub r1cs_verifier_proof: R1CSVerifierProof, +// pub r: (Vec, Vec), +// } + +// pub struct TestudoNizkGens { +// gens_r1cs_sat: R1CSGens, +// } + +// impl TestudoNizkGens { +// /// Performs the setup required by the polynomial commitment PST and Groth16 +// pub fn setup( +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// // ensure num_vars is a power of 2 +// let num_vars_padded = { +// let mut num_vars_padded = max(num_vars, num_inputs + 1); +// if num_vars_padded != num_vars_padded.next_power_of_two() { +// num_vars_padded = num_vars_padded.next_power_of_two(); +// } +// num_vars_padded +// }; + +// let num_cons_padded = { +// let mut num_cons_padded = num_cons; + +// // ensure that num_cons_padded is at least 2 +// if num_cons_padded == 0 || num_cons_padded == 1 { +// num_cons_padded = 2; +// } + +// // ensure that num_cons_padded is a power of 2 +// if num_cons.next_power_of_two() != num_cons { +// num_cons_padded = num_cons.next_power_of_two(); +// } +// num_cons_padded +// }; + +// let gens_r1cs_sat = R1CSGens::setup( +// b"gens_r1cs_sat", +// num_cons_padded, +// num_vars_padded, +// num_inputs, +// poseidon, +// ); +// TestudoNizkGens { gens_r1cs_sat } +// } +// } + +// impl TestudoNizk +// where +// E::ScalarField: Absorb, +// { +// // Returns a proof that the R1CS instance is satisfiable +// pub fn prove( +// inst: &Instance, +// vars: VarsAssignment, +// inputs: &InputsAssignment, +// gens: &TestudoNizkGens, +// transcript: &mut PoseidonTranscript, +// poseidon: PoseidonConfig, +// ) -> Result, ProofVerifyError> { +// transcript.append_bytes(b"", &inst.digest); + +// let c: E::ScalarField = transcript.challenge_scalar(b""); +// transcript.new_from_state(&c); + +// // we might need to pad variables +// let padded_vars = { +// let num_padded_vars = inst.inst.get_num_vars(); +// let num_vars = vars.assignment.len(); +// if num_padded_vars > num_vars { +// vars.pad(num_padded_vars) +// } else { +// vars +// } +// }; + +// let (r1cs_sat_proof, rx, ry) = R1CSProof::prove( +// &inst.inst, +// padded_vars.assignment, +// &inputs.assignment, +// &gens.gens_r1cs_sat, +// transcript, +// ); + +// let inst_evals = inst.inst.evaluate(&rx, &ry); + +// transcript.new_from_state(&c); +// let r1cs_verifier_proof = r1cs_sat_proof +// .prove_verifier( +// inst.inst.get_num_vars(), +// inst.inst.get_num_cons(), +// &inputs.assignment, +// &inst_evals, +// transcript, +// &gens.gens_r1cs_sat, +// poseidon, +// ) +// .unwrap(); +// Ok(TestudoNizk { +// r1cs_verifier_proof, +// r: (rx, ry), +// }) +// } + +// // Verifies the satisfiability proof for the R1CS instance. In NIZK mode, the +// // verifier evaluates matrices A, B and C themselves, which is a linear +// // operation and hence this is not a SNARK. +// // However, for highly structured circuits this operation is fast. +// pub fn verify( +// &self, +// gens: &TestudoNizkGens, +// inst: &Instance, +// input: &InputsAssignment, +// transcript: &mut PoseidonTranscript, +// _poseidon: PoseidonConfig, +// ) -> Result { +// transcript.append_bytes(b"", &inst.digest); +// let (claimed_rx, claimed_ry) = &self.r; +// let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry); + +// let sat_verified = self.r1cs_verifier_proof.verify( +// (claimed_rx.clone(), claimed_ry.clone()), +// &input.assignment, +// &inst_evals, +// transcript, +// &gens.gens_r1cs_sat, +// )?; +// assert!(sat_verified == true); +// Ok(sat_verified) +// } +// } + +// #[cfg(test)] +// mod tests { +// use crate::{ +// parameters::poseidon_params, +// poseidon_transcript::PoseidonTranscript, +// testudo_nizk::{TestudoNizk, TestudoNizkGens}, +// Instance, +// }; + +// #[test] +// pub fn check_testudo_nizk() { +// let num_vars = 256; +// let num_cons = num_vars; +// let num_inputs = 10; + +// type E = ark_bls12_377::Bls12_377; + +// // produce public generators +// let gens = TestudoNizkGens::::setup(num_cons, num_vars, num_inputs, poseidon_params()); + +// // produce a synthetic R1CSInstance +// let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + +// let params = poseidon_params(); + +// // produce a proof +// let mut prover_transcript = PoseidonTranscript::new(¶ms); +// let proof = +// TestudoNizk::prove(&inst, vars, &inputs, &gens, &mut prover_transcript, params).unwrap(); + +// // verify the proof +// let mut verifier_transcript = PoseidonTranscript::new(&poseidon_params()); +// assert!(proof +// .verify( +// &gens, +// &inst, +// &inputs, +// &mut verifier_transcript, +// poseidon_params() +// ) +// .is_ok()); +// } +// } diff --git a/src/testudo_snark.rs b/src/testudo_snark.rs index e6cb430a..d8a6fb33 100644 --- a/src/testudo_snark.rs +++ b/src/testudo_snark.rs @@ -1,377 +1,377 @@ -use std::cmp::max; - -use crate::errors::ProofVerifyError; -use crate::r1csinstance::{R1CSCommitmentGens, R1CSEvalProof}; -use crate::r1csproof::R1CSVerifierProof; - -use crate::timer::Timer; -use crate::transcript::TranscriptWriter; -use crate::{ - poseidon_transcript::PoseidonTranscript, - r1csproof::{R1CSGens, R1CSProof}, - transcript::Transcript, - InputsAssignment, Instance, VarsAssignment, -}; -use crate::{ComputationCommitment, ComputationDecommitment}; -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use ark_ec::pairing::Pairing; - -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; - -#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] - -pub struct TestudoSnark { - pub r1cs_verifier_proof: R1CSVerifierProof, - pub r1cs_eval_proof: R1CSEvalProof, - pub inst_evals: (E::ScalarField, E::ScalarField, E::ScalarField), - pub r: (Vec, Vec), -} - -pub struct TestudoSnarkGens { - gens_r1cs_sat: R1CSGens, - gens_r1cs_eval: R1CSCommitmentGens, -} - -impl TestudoSnarkGens { - /// Performs the setups required by the polynomial commitment PST, Groth16 - /// and the computational commitment given the size of the R1CS statement, - /// `num_nz_entries` specifies the maximum number of non-zero entries in - /// any of the three R1CS matrices. - pub fn setup( - num_cons: usize, - num_vars: usize, - num_inputs: usize, - num_nz_entries: usize, - poseidon: PoseidonConfig, - ) -> Self { - // ensure num_vars is a power of 2 - let num_vars_padded = { - let mut num_vars_padded = max(num_vars, num_inputs + 1); - if num_vars_padded != num_vars_padded.next_power_of_two() { - num_vars_padded = num_vars_padded.next_power_of_two(); - } - num_vars_padded - }; - - let num_cons_padded = { - let mut num_cons_padded = num_cons; - - // ensure that num_cons_padded is at least 2 - if num_cons_padded == 0 || num_cons_padded == 1 { - num_cons_padded = 2; - } - - // ensure that num_cons_padded is a power of 2 - if num_cons.next_power_of_two() != num_cons { - num_cons_padded = num_cons.next_power_of_two(); - } - num_cons_padded - }; - - let gens_r1cs_sat = R1CSGens::setup( - b"gens_r1cs_sat", - num_cons_padded, - num_vars_padded, - num_inputs, - poseidon, - ); - let gens_r1cs_eval = R1CSCommitmentGens::setup( - b"gens_r1cs_eval", - num_cons_padded, - num_vars_padded, - num_inputs, - num_nz_entries, - ); - TestudoSnarkGens { - gens_r1cs_sat, - gens_r1cs_eval, - } - } -} - -impl TestudoSnark -where - E::ScalarField: Absorb, -{ - // Constructs the computational commitment, used to prove that the - // evaluations of matrices A, B and C sent by the prover to the verifier - // are correct. - pub fn encode( - inst: &Instance, - gens: &TestudoSnarkGens, - ) -> ( - ComputationCommitment, - ComputationDecommitment, - ) { - let timer_encode = Timer::new("SNARK::encode"); - let (comm, decomm) = inst.inst.commit(&gens.gens_r1cs_eval); - timer_encode.stop(); - ( - ComputationCommitment { comm }, - ComputationDecommitment { decomm }, - ) - } - - // Returns the Testudo SNARK proof which has two components: - // * proof that the R1CS instance is satisfiable - // * proof that the evlauation of matrices A, B and C on point (x,y) - // resulted from the two rounda of sumcheck are correct - pub fn prove( - inst: &Instance, - comm: &ComputationCommitment, - decomm: &ComputationDecommitment, - vars: VarsAssignment, - inputs: &InputsAssignment, - gens: &TestudoSnarkGens, - transcript: &mut PoseidonTranscript, - poseidon: PoseidonConfig, - ) -> Result, ProofVerifyError> { - comm.comm.write_to_transcript(transcript); - let c: E::ScalarField = transcript.challenge_scalar(b""); - transcript.new_from_state(&c); - - // we might need to pad variables - let padded_vars = { - let num_padded_vars = inst.inst.get_num_vars(); - let num_vars = vars.assignment.len(); - if num_padded_vars > num_vars { - vars.pad(num_padded_vars) - } else { - vars - } - }; - - let (r1cs_sat_proof, rx, ry) = R1CSProof::prove( - &inst.inst, - padded_vars.assignment, - &inputs.assignment, - &gens.gens_r1cs_sat, - transcript, - ); - - // We send evaluations of A, B, C at r = (rx, ry) as claims - // to enable the verifier complete the first sum-check - let timer_eval = Timer::new("eval_sparse_polys"); - let inst_evals = { - let (Ar, Br, Cr) = inst.inst.evaluate(&rx, &ry); - transcript.append_scalar(b"", &Ar); - transcript.append_scalar(b"", &Br); - transcript.append_scalar(b"", &Cr); - (Ar, Br, Cr) - }; - timer_eval.stop(); - - let timer_eval_proof = Timer::new("r1cs_eval_proof"); - let r1cs_eval_proof = R1CSEvalProof::prove( - &decomm.decomm, - &rx, - &ry, - &inst_evals, - &gens.gens_r1cs_eval, - transcript, - ); - timer_eval_proof.stop(); - - transcript.new_from_state(&c); - let timer_sat_circuit_verification = Timer::new("r1cs_sat_circuit_verification"); - let r1cs_verifier_proof = r1cs_sat_proof - .prove_verifier( - inst.inst.get_num_vars(), - inst.inst.get_num_cons(), - &inputs.assignment, - &inst_evals, - transcript, - &gens.gens_r1cs_sat, - poseidon, - ) - .unwrap(); - timer_sat_circuit_verification.stop(); - Ok(TestudoSnark { - r1cs_verifier_proof, - r1cs_eval_proof, - inst_evals, - r: (rx, ry), - }) - } - - pub fn verify( - &self, - gens: &TestudoSnarkGens, - comm: &ComputationCommitment, - input: &InputsAssignment, - transcript: &mut PoseidonTranscript, - _poseidon: PoseidonConfig, - ) -> Result { - let (rx, ry) = &self.r; - - let timer_sat_verification = Timer::new("r1cs_sat_verification"); - let sat_verified = self.r1cs_verifier_proof.verify( - (rx.clone(), ry.clone()), - &input.assignment, - &self.inst_evals, - transcript, - &gens.gens_r1cs_sat, - )?; - timer_sat_verification.stop(); - assert!(sat_verified == true); - - let (Ar, Br, Cr) = &self.inst_evals; - transcript.append_scalar(b"", Ar); - transcript.append_scalar(b"", Br); - transcript.append_scalar(b"", Cr); - - let timer_eval_verification = Timer::new("r1cs_eval_verification"); - let eval_verified = self.r1cs_eval_proof.verify( - &comm.comm, - rx, - ry, - &self.inst_evals, - &gens.gens_r1cs_eval, - transcript, - ); - timer_eval_verification.stop(); - Ok(sat_verified && eval_verified.is_ok()) - } -} - -#[cfg(test)] -mod tests { - - use crate::ark_std::Zero; - use crate::{ - parameters::poseidon_params, - poseidon_transcript::PoseidonTranscript, - testudo_snark::{TestudoSnark, TestudoSnarkGens}, - InputsAssignment, Instance, VarsAssignment, - }; - use ark_ff::{BigInteger, One, PrimeField}; - - #[test] - pub fn check_testudo_snark() { - let num_vars = 256; - let num_cons = num_vars; - let num_inputs = 10; - - type E = ark_bls12_377::Bls12_377; - - // produce public generators - let gens = - TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, poseidon_params()); - - // produce a synthetic R1CSInstance - let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - // create a commitment to R1CSInstance - let (comm, decomm) = TestudoSnark::encode(&inst, &gens); - - let params = poseidon_params(); - - // produce a proof - let mut prover_transcript = PoseidonTranscript::new(¶ms); - let proof = TestudoSnark::prove( - &inst, - &comm, - &decomm, - vars, - &inputs, - &gens, - &mut prover_transcript, - params, - ) - .unwrap(); - - // verify the proof - let mut verifier_transcript = PoseidonTranscript::new(&poseidon_params()); - assert!(proof - .verify( - &gens, - &comm, - &inputs, - &mut verifier_transcript, - poseidon_params() - ) - .is_ok()); - } - - #[test] - fn test_padded_constraints() { - type F = ark_bls12_377::Fr; - type E = ark_bls12_377::Bls12_377; - // parameters of the R1CS instance - let num_cons = 1; - let num_vars = 0; - let num_inputs = 3; - let num_non_zero_entries = 3; - - // We will encode the above constraints into three matrices, where - // the coefficients in the matrix are in the little-endian byte order - let mut A: Vec<(usize, usize, Vec)> = Vec::new(); - let mut B: Vec<(usize, usize, Vec)> = Vec::new(); - let mut C: Vec<(usize, usize, Vec)> = Vec::new(); - - // Create a^2 + b + 13 - A.push((0, num_vars + 2, (F::one().into_bigint().to_bytes_le()))); // 1*a - B.push((0, num_vars + 2, F::one().into_bigint().to_bytes_le())); // 1*a - C.push((0, num_vars + 1, F::one().into_bigint().to_bytes_le())); // 1*z - C.push((0, num_vars, (-F::from(13u64)).into_bigint().to_bytes_le())); // -13*1 - C.push((0, num_vars + 3, (-F::one()).into_bigint().to_bytes_le())); // -1*b - - // Var Assignments (Z_0 = 16 is the only output) - let vars = vec![F::zero().into_bigint().to_bytes_le(); num_vars]; - - // create an InputsAssignment (a = 1, b = 2) - let mut inputs = vec![F::zero().into_bigint().to_bytes_le(); num_inputs]; - inputs[0] = F::from(16u64).into_bigint().to_bytes_le(); - inputs[1] = F::from(1u64).into_bigint().to_bytes_le(); - inputs[2] = F::from(2u64).into_bigint().to_bytes_le(); - - let assignment_inputs = InputsAssignment::::new(&inputs).unwrap(); - let assignment_vars = VarsAssignment::new(&vars).unwrap(); - - // Check if instance is satisfiable - let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap(); - let res = inst.is_sat(&assignment_vars, &assignment_inputs); - assert!(res.unwrap(), "should be satisfied"); - - // Testudo public params - let gens = TestudoSnarkGens::::setup( - num_cons, - num_vars, - num_inputs, - num_non_zero_entries, - poseidon_params(), - ); - - // create a commitment to the R1CS instance - let (comm, decomm) = TestudoSnark::encode(&inst, &gens); - - let params = poseidon_params(); - - // produce a TestudoSnark - let mut prover_transcript = PoseidonTranscript::new(¶ms); - let proof = TestudoSnark::prove( - &inst, - &comm, - &decomm, - assignment_vars.clone(), - &assignment_inputs, - &gens, - &mut prover_transcript, - poseidon_params(), - ) - .unwrap(); - - // verify the TestudoSnark - let mut verifier_transcript = PoseidonTranscript::new(¶ms); - assert!(proof - .verify( - &gens, - &comm, - &assignment_inputs, - &mut verifier_transcript, - poseidon_params() - ) - .is_ok()); - } -} +// use std::cmp::max; + +// use crate::errors::ProofVerifyError; +// use crate::r1csinstance::{R1CSCommitmentGens, R1CSEvalProof}; +// use crate::r1csproof::R1CSVerifierProof; + +// use crate::timer::Timer; +// use crate::transcript::TranscriptWriter; +// use crate::{ +// poseidon_transcript::PoseidonTranscript, +// r1csproof::{R1CSGens, R1CSProof}, +// transcript::Transcript, +// InputsAssignment, Instance, VarsAssignment, +// }; +// use crate::{ComputationCommitment, ComputationDecommitment}; +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; + +// use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; + +// #[derive(Debug, CanonicalSerialize, CanonicalDeserialize)] + +// pub struct TestudoSnark { +// pub r1cs_verifier_proof: R1CSVerifierProof, +// pub r1cs_eval_proof: R1CSEvalProof, +// pub inst_evals: (E::ScalarField, E::ScalarField, E::ScalarField), +// pub r: (Vec, Vec), +// } + +// pub struct TestudoSnarkGens { +// gens_r1cs_sat: R1CSGens, +// gens_r1cs_eval: R1CSCommitmentGens, +// } + +// impl TestudoSnarkGens { +// /// Performs the setups required by the polynomial commitment PST, Groth16 +// /// and the computational commitment given the size of the R1CS statement, +// /// `num_nz_entries` specifies the maximum number of non-zero entries in +// /// any of the three R1CS matrices. +// pub fn setup( +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// num_nz_entries: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// // ensure num_vars is a power of 2 +// let num_vars_padded = { +// let mut num_vars_padded = max(num_vars, num_inputs + 1); +// if num_vars_padded != num_vars_padded.next_power_of_two() { +// num_vars_padded = num_vars_padded.next_power_of_two(); +// } +// num_vars_padded +// }; + +// let num_cons_padded = { +// let mut num_cons_padded = num_cons; + +// // ensure that num_cons_padded is at least 2 +// if num_cons_padded == 0 || num_cons_padded == 1 { +// num_cons_padded = 2; +// } + +// // ensure that num_cons_padded is a power of 2 +// if num_cons.next_power_of_two() != num_cons { +// num_cons_padded = num_cons.next_power_of_two(); +// } +// num_cons_padded +// }; + +// let gens_r1cs_sat = R1CSGens::setup( +// b"gens_r1cs_sat", +// num_cons_padded, +// num_vars_padded, +// num_inputs, +// poseidon, +// ); +// let gens_r1cs_eval = R1CSCommitmentGens::setup( +// b"gens_r1cs_eval", +// num_cons_padded, +// num_vars_padded, +// num_inputs, +// num_nz_entries, +// ); +// TestudoSnarkGens { +// gens_r1cs_sat, +// gens_r1cs_eval, +// } +// } +// } + +// impl TestudoSnark +// where +// E::ScalarField: Absorb, +// { +// // Constructs the computational commitment, used to prove that the +// // evaluations of matrices A, B and C sent by the prover to the verifier +// // are correct. +// pub fn encode( +// inst: &Instance, +// gens: &TestudoSnarkGens, +// ) -> ( +// ComputationCommitment, +// ComputationDecommitment, +// ) { +// let timer_encode = Timer::new("SNARK::encode"); +// let (comm, decomm) = inst.inst.commit(&gens.gens_r1cs_eval); +// timer_encode.stop(); +// ( +// ComputationCommitment { comm }, +// ComputationDecommitment { decomm }, +// ) +// } + +// // Returns the Testudo SNARK proof which has two components: +// // * proof that the R1CS instance is satisfiable +// // * proof that the evlauation of matrices A, B and C on point (x,y) +// // resulted from the two rounda of sumcheck are correct +// pub fn prove( +// inst: &Instance, +// comm: &ComputationCommitment, +// decomm: &ComputationDecommitment, +// vars: VarsAssignment, +// inputs: &InputsAssignment, +// gens: &TestudoSnarkGens, +// transcript: &mut PoseidonTranscript, +// poseidon: PoseidonConfig, +// ) -> Result, ProofVerifyError> { +// comm.comm.write_to_transcript(transcript); +// let c: E::ScalarField = transcript.challenge_scalar(b""); +// transcript.new_from_state(&c); + +// // we might need to pad variables +// let padded_vars = { +// let num_padded_vars = inst.inst.get_num_vars(); +// let num_vars = vars.assignment.len(); +// if num_padded_vars > num_vars { +// vars.pad(num_padded_vars) +// } else { +// vars +// } +// }; + +// let (r1cs_sat_proof, rx, ry) = R1CSProof::prove( +// &inst.inst, +// padded_vars.assignment, +// &inputs.assignment, +// &gens.gens_r1cs_sat, +// transcript, +// ); + +// // We send evaluations of A, B, C at r = (rx, ry) as claims +// // to enable the verifier complete the first sum-check +// let timer_eval = Timer::new("eval_sparse_polys"); +// let inst_evals = { +// let (Ar, Br, Cr) = inst.inst.evaluate(&rx, &ry); +// transcript.append_scalar(b"", &Ar); +// transcript.append_scalar(b"", &Br); +// transcript.append_scalar(b"", &Cr); +// (Ar, Br, Cr) +// }; +// timer_eval.stop(); + +// let timer_eval_proof = Timer::new("r1cs_eval_proof"); +// let r1cs_eval_proof = R1CSEvalProof::prove( +// &decomm.decomm, +// &rx, +// &ry, +// &inst_evals, +// &gens.gens_r1cs_eval, +// transcript, +// ); +// timer_eval_proof.stop(); + +// transcript.new_from_state(&c); +// let timer_sat_circuit_verification = Timer::new("r1cs_sat_circuit_verification"); +// let r1cs_verifier_proof = r1cs_sat_proof +// .prove_verifier( +// inst.inst.get_num_vars(), +// inst.inst.get_num_cons(), +// &inputs.assignment, +// &inst_evals, +// transcript, +// &gens.gens_r1cs_sat, +// poseidon, +// ) +// .unwrap(); +// timer_sat_circuit_verification.stop(); +// Ok(TestudoSnark { +// r1cs_verifier_proof, +// r1cs_eval_proof, +// inst_evals, +// r: (rx, ry), +// }) +// } + +// pub fn verify( +// &self, +// gens: &TestudoSnarkGens, +// comm: &ComputationCommitment, +// input: &InputsAssignment, +// transcript: &mut PoseidonTranscript, +// _poseidon: PoseidonConfig, +// ) -> Result { +// let (rx, ry) = &self.r; + +// let timer_sat_verification = Timer::new("r1cs_sat_verification"); +// let sat_verified = self.r1cs_verifier_proof.verify( +// (rx.clone(), ry.clone()), +// &input.assignment, +// &self.inst_evals, +// transcript, +// &gens.gens_r1cs_sat, +// )?; +// timer_sat_verification.stop(); +// assert!(sat_verified == true); + +// let (Ar, Br, Cr) = &self.inst_evals; +// transcript.append_scalar(b"", Ar); +// transcript.append_scalar(b"", Br); +// transcript.append_scalar(b"", Cr); + +// let timer_eval_verification = Timer::new("r1cs_eval_verification"); +// let eval_verified = self.r1cs_eval_proof.verify( +// &comm.comm, +// rx, +// ry, +// &self.inst_evals, +// &gens.gens_r1cs_eval, +// transcript, +// ); +// timer_eval_verification.stop(); +// Ok(sat_verified && eval_verified.is_ok()) +// } +// } + +// #[cfg(test)] +// mod tests { + +// use crate::ark_std::Zero; +// use crate::{ +// parameters::poseidon_params, +// poseidon_transcript::PoseidonTranscript, +// testudo_snark::{TestudoSnark, TestudoSnarkGens}, +// InputsAssignment, Instance, VarsAssignment, +// }; +// use ark_ff::{BigInteger, One, PrimeField}; + +// #[test] +// pub fn check_testudo_snark() { +// let num_vars = 256; +// let num_cons = num_vars; +// let num_inputs = 10; + +// type E = ark_bls12_377::Bls12_377; + +// // produce public generators +// let gens = +// TestudoSnarkGens::::setup(num_cons, num_vars, num_inputs, num_cons, poseidon_params()); + +// // produce a synthetic R1CSInstance +// let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + +// // create a commitment to R1CSInstance +// let (comm, decomm) = TestudoSnark::encode(&inst, &gens); + +// let params = poseidon_params(); + +// // produce a proof +// let mut prover_transcript = PoseidonTranscript::new(¶ms); +// let proof = TestudoSnark::prove( +// &inst, +// &comm, +// &decomm, +// vars, +// &inputs, +// &gens, +// &mut prover_transcript, +// params, +// ) +// .unwrap(); + +// // verify the proof +// let mut verifier_transcript = PoseidonTranscript::new(&poseidon_params()); +// assert!(proof +// .verify( +// &gens, +// &comm, +// &inputs, +// &mut verifier_transcript, +// poseidon_params() +// ) +// .is_ok()); +// } + +// #[test] +// fn test_padded_constraints() { +// type F = ark_bls12_377::Fr; +// type E = ark_bls12_377::Bls12_377; +// // parameters of the R1CS instance +// let num_cons = 1; +// let num_vars = 0; +// let num_inputs = 3; +// let num_non_zero_entries = 3; + +// // We will encode the above constraints into three matrices, where +// // the coefficients in the matrix are in the little-endian byte order +// let mut A: Vec<(usize, usize, Vec)> = Vec::new(); +// let mut B: Vec<(usize, usize, Vec)> = Vec::new(); +// let mut C: Vec<(usize, usize, Vec)> = Vec::new(); + +// // Create a^2 + b + 13 +// A.push((0, num_vars + 2, (F::one().into_bigint().to_bytes_le()))); // 1*a +// B.push((0, num_vars + 2, F::one().into_bigint().to_bytes_le())); // 1*a +// C.push((0, num_vars + 1, F::one().into_bigint().to_bytes_le())); // 1*z +// C.push((0, num_vars, (-F::from(13u64)).into_bigint().to_bytes_le())); // -13*1 +// C.push((0, num_vars + 3, (-F::one()).into_bigint().to_bytes_le())); // -1*b + +// // Var Assignments (Z_0 = 16 is the only output) +// let vars = vec![F::zero().into_bigint().to_bytes_le(); num_vars]; + +// // create an InputsAssignment (a = 1, b = 2) +// let mut inputs = vec![F::zero().into_bigint().to_bytes_le(); num_inputs]; +// inputs[0] = F::from(16u64).into_bigint().to_bytes_le(); +// inputs[1] = F::from(1u64).into_bigint().to_bytes_le(); +// inputs[2] = F::from(2u64).into_bigint().to_bytes_le(); + +// let assignment_inputs = InputsAssignment::::new(&inputs).unwrap(); +// let assignment_vars = VarsAssignment::new(&vars).unwrap(); + +// // Check if instance is satisfiable +// let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap(); +// let res = inst.is_sat(&assignment_vars, &assignment_inputs); +// assert!(res.unwrap(), "should be satisfied"); + +// // Testudo public params +// let gens = TestudoSnarkGens::::setup( +// num_cons, +// num_vars, +// num_inputs, +// num_non_zero_entries, +// poseidon_params(), +// ); + +// // create a commitment to the R1CS instance +// let (comm, decomm) = TestudoSnark::encode(&inst, &gens); + +// let params = poseidon_params(); + +// // produce a TestudoSnark +// let mut prover_transcript = PoseidonTranscript::new(¶ms); +// let proof = TestudoSnark::prove( +// &inst, +// &comm, +// &decomm, +// assignment_vars.clone(), +// &assignment_inputs, +// &gens, +// &mut prover_transcript, +// poseidon_params(), +// ) +// .unwrap(); + +// // verify the TestudoSnark +// let mut verifier_transcript = PoseidonTranscript::new(¶ms); +// assert!(proof +// .verify( +// &gens, +// &comm, +// &assignment_inputs, +// &mut verifier_transcript, +// poseidon_params() +// ) +// .is_ok()); +// } +// } diff --git a/src/verifier_circuit.rs b/src/verifier_circuit.rs index 2304d2e8..e5071625 100644 --- a/src/verifier_circuit.rs +++ b/src/verifier_circuit.rs @@ -1,150 +1,577 @@ -use crate::ark_std::One; -use crate::constraints::R1CSVerificationCircuit; -use crate::mipp::MippProof; -use crate::parameters::get_bls12377_fq_params; -use crate::parameters::params_to_base_field; -use crate::r1csproof::R1CSGens; -use crate::r1csproof::R1CSVerifierProof; -use crate::constraints::VerifierConfig; -use crate::{ - math::Math, - poseidon_transcript::PoseidonTranscript, - sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, - unipoly::UniPoly, -}; -use ark_crypto_primitives::snark::SNARKGadget; -use ark_ec::CurveGroup; -use ark_ff::Field; -use ark_groth16::constraints::Groth16VerifierGadget; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::{ - constraints::CryptographicSpongeVar, - poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -}; -use ark_crypto_primitives::Error; -use ark_ec::pairing::Pairing; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_groth16::Groth16; -use ark_groth16::PreparedVerifyingKey; -use ark_groth16::constraints::PreparedVerifyingKeyVar; -use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; -use ark_poly_commit::multilinear_pc::data_structures::ProofG1; -use ark_poly_commit::multilinear_pc::{ - data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, - MultilinearPC, -}; -use ark_r1cs_std::groups::bls12::G1Var; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::{ - alloc::{AllocVar, AllocationMode}, - fields::fp::FpVar, - prelude::{EqGadget, FieldVar}, -}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; -use ark_serialize::Compress; -use ark_snark::CircuitSpecificSetupSNARK; -use ark_snark::SNARK; -use digest::generic_array::typenum::True; -use rand::CryptoRng; -use rand::Rng; -use std::ops::AddAssign; -use std::ops::Mul; -use std::ops::MulAssign; -use std::{borrow::Borrow, marker::PhantomData}; -use ark_groth16; -type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; - -pub struct VerifierCircuit -where - E: Pairing, - IV: PairingVar>, -{ - // pub inner_circuit: R1CSVerificationCircuit, // circuito Mara - - // pub inner_proof: ark_groth16::Proof, // PROOF DA VERIFICARE - // pub inner_vk: PreparedVerifyingKey, // GENS.GC.VK - - pub r: (Vec, Vec), - pub input: Vec, - pub evals: (E::ScalarField,E::ScalarField,E::ScalarField), - - pub transcript: PoseidonTranscript, - pub gens: R1CSGens, - pub r1cs_proof: R1CSVerifierProof, // SELF - pub _iv: PhantomData, -} - -impl VerifierCircuit -where - E: Pairing, - IV: PairingVar>, -{ - pub fn new( - //config: &VerifierConfig, - //mut rng: &mut R, - r: (Vec, Vec), - input: Vec, - evals: (E::ScalarField, E::ScalarField, E::ScalarField), - transcript: PoseidonTranscript, - gens: R1CSGens, - r1cs_proof: R1CSVerifierProof, - ) -> Result { - // let inner_circuit = crate::constraints::R1CSVerificationCircuit::new(config); - // let (pk, vk) = Groth16::::setup(inner_circuit.clone(), &mut rng).unwrap(); - // let proof = Groth16::::prove(&pk, inner_circuit.clone(), &mut rng)?; - // let pvk = Groth16::::process_vk(&vk).unwrap(); - Ok(Self { - // inner_circuit, - // inner_proof: proof, - // inner_vk: pvk, - r: r, - input: input.to_vec(), - evals: evals, - transcript: transcript, - gens: gens, - r1cs_proof, - _iv: PhantomData, - }) - } -} -impl ConstraintSynthesizer> for VerifierCircuit -where -E: Pairing, -IV: PairingVar>, - -//IV::G1Var: CurveVar, -// IV::G2Var: CurveVar, -// IV::GTVar: FieldVar, -{ - fn generate_constraints(self, cs: ConstraintSystemRef>) -> ark_relations::r1cs::Result<()> { - - // //STEP 1) ALLOCATE INNER_PROOF AS CIRCUIT VARIABLE - - let (rx, ry) = self.r; - let (Ar, Br, Cr) = self.evals; - let mut pubs = vec![self.r1cs_proof.initial_state]; - pubs.extend(self.input.clone()); - pubs.extend(rx.clone()); - pubs.extend(ry.clone()); - pubs.extend(vec![ - self.r1cs_proof.eval_vars_at_ry, - Ar, - Br, - Cr, - self.r1cs_proof.transcript_sat_state, - ]); - // self.transcript.new_from_state(self.r1cs_proof.transcript_sat_state); - - - - let proof_gadget = as SNARKGadget,Groth16>>::ProofVar::new_witness(cs.clone(), || Ok(self.r1cs_proof.circuit_proof)).unwrap(); - let vk_gadget = as SNARKGadget,Groth16>>::VerifyingKeyVar::new_witness(cs.clone(), || Ok(self.gens.gens_gc.vk.clone())).unwrap(); - - let input_gadget= as SNARKGadget,Groth16>>::InputVar::new_input(cs.clone(), || Ok(pubs)).unwrap(); - let ver = as SNARKGadget,Groth16>>::verify(&vk_gadget, &input_gadget, &proof_gadget).unwrap(); - println!("Verifier groth circuit"); - ver.enforce_equal(&Boolean::constant(true)).unwrap(); - Ok(()) - } -} \ No newline at end of file +// use crate::ark_std::One; +// use crate::constraints::R1CSVerificationCircuit; +// use crate::mipp::MippProof; +// use crate::parameters::get_bls12377_fq_params; +// use crate::parameters::params_to_base_field; +// use crate::r1csproof::R1CSGens; +// use crate::r1csproof::R1CSVerifierProof; +// use crate::constraints::VerifierConfig; +// use ark_serialize::CanonicalSerialize; +// use crate::{ +// math::Math, +// poseidon_transcript::PoseidonTranscript, +// sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, +// unipoly::UniPoly, +// }; +// use ark_ec::Group; +// use ark_crypto_primitives::snark::SNARKGadget; +// use ark_ec::CurveGroup; +// use ark_ff::Field; +// use ark_groth16::constraints::Groth16VerifierGadget; +// use ark_crypto_primitives::sponge::constraints::AbsorbGadget; +// use ark_crypto_primitives::sponge::{ +// constraints::CryptographicSpongeVar, +// poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +// }; +// use ark_crypto_primitives::Error; +// use ark_ec::pairing::Pairing; +// use ark_ff::BigInteger; +// use ark_ff::PrimeField; +// use ark_groth16::Groth16; +// use ark_groth16::PreparedVerifyingKey; +// use ark_groth16::constraints::PreparedVerifyingKeyVar; +// use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; +// use ark_poly_commit::multilinear_pc::data_structures::ProofG1; +// use ark_poly_commit::multilinear_pc::{ +// data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, +// MultilinearPC, +// }; +// use ark_r1cs_std::groups::bls12::G1Var; +// use ark_r1cs_std::prelude::*; +// use ark_r1cs_std::{ +// alloc::{AllocVar, AllocationMode}, +// fields::fp::FpVar, +// prelude::{EqGadget, FieldVar}, +// }; +// use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; +// use ark_serialize::Compress; +// use ark_snark::CircuitSpecificSetupSNARK; +// use ark_snark::SNARK; +// use digest::generic_array::typenum::True; +// use rand::CryptoRng; +// use rand::Rng; +// use std::ops::AddAssign; +// use std::ops::Mul; +// use std::ops::MulAssign; +// use std::{borrow::Borrow, marker::PhantomData}; +// use ark_groth16; +// type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; + +// pub struct VerifierCircuit +// where +// E: Pairing, +// IV: PairingVar>, +// { +// // pub inner_circuit: R1CSVerificationCircuit, // circuito Mara + +// // pub inner_proof: ark_groth16::Proof, // PROOF DA VERIFICARE +// // pub inner_vk: PreparedVerifyingKey, // GENS.GC.VK + +// pub r: (Vec, Vec), +// pub input: Vec, +// pub evals: (E::ScalarField,E::ScalarField,E::ScalarField), + +// pub transcript: PoseidonTranscript, +// pub gens: R1CSGens, +// pub r1cs_proof: R1CSVerifierProof, // SELF +// pub _iv: PhantomData, +// } + +// impl VerifierCircuit +// where +// E: Pairing, +// IV: PairingVar>, +// { +// pub fn new( +// //config: &VerifierConfig, +// //mut rng: &mut R, +// r: (Vec, Vec), +// input: Vec, +// evals: (E::ScalarField, E::ScalarField, E::ScalarField), +// transcript: PoseidonTranscript, +// gens: R1CSGens, +// r1cs_proof: R1CSVerifierProof, +// ) -> Result { +// // let inner_circuit = crate::constraints::R1CSVerificationCircuit::new(config); +// // let (pk, vk) = Groth16::::setup(inner_circuit.clone(), &mut rng).unwrap(); +// // let proof = Groth16::::prove(&pk, inner_circuit.clone(), &mut rng)?; +// // let pvk = Groth16::::process_vk(&vk).unwrap(); +// Ok(Self { +// // inner_circuit, +// // inner_proof: proof, +// // inner_vk: pvk, +// r: r, +// input: input.to_vec(), +// evals: evals, +// transcript: transcript, +// gens: gens, +// r1cs_proof, +// _iv: PhantomData, +// }) +// } +// } +// impl ConstraintSynthesizer> for VerifierCircuit +// where +// E: Pairing, +// IV: PairingVar>, +// IV::G1Var: CurveVar>, +// // IV::G2Var: CurveVar, +// // IV::GTVar: FieldVar, +// { +// fn generate_constraints(self, cs: ConstraintSystemRef>) -> ark_relations::r1cs::Result<()> { + +// // //STEP 1) ALLOCATE INNER_PROOF AS CIRCUIT VARIABLE + +// let (rx, ry) = self.r; +// let (Ar, Br, Cr) = self.evals; +// let mut pubs = vec![self.r1cs_proof.initial_state]; +// pubs.extend(self.input.clone()); +// pubs.extend(rx.clone()); +// pubs.extend(ry.clone()); +// pubs.extend(vec![ +// self.r1cs_proof.eval_vars_at_ry, +// Ar, +// Br, +// Cr, +// self.r1cs_proof.transcript_sat_state, +// ]); +// // self.transcript.new_from_state(self.r1cs_proof.transcript_sat_state); + + + +// let proof_gadget = as SNARKGadget,Groth16>>::ProofVar::new_witness(cs.clone(), || Ok(self.r1cs_proof.circuit_proof)).unwrap(); +// let vk_gadget = as SNARKGadget,Groth16>>::VerifyingKeyVar::new_witness(cs.clone(), || Ok(self.gens.gens_gc.vk.clone())).unwrap(); + +// let input_gadget= as SNARKGadget,Groth16>>::InputVar::new_input(cs.clone(), || Ok(pubs)).unwrap(); +// let ver = as SNARKGadget,Groth16>>::verify(&vk_gadget, &input_gadget, &proof_gadget).unwrap(); +// println!("Verifier groth circuit"); +// ver.enforce_equal(&Boolean::constant(true)).unwrap(); + +// // MAPPA DEI PARAMETRI PER CHIAMARE VERIFY +// //gens.gens_pc.vk = vk +// // self.comm = r1cs_proof.comm +// //ry[1..] = point +// // self.eval_vars_at_ry = v +// // self.proof_evals_vars_at_ry = pst_proof +// // self.mipp_proof =mipp_proof +// // selft.t = T +// ver_mipp_pst::(cs, self.gens.gens_pc.vk, self.r1cs_proof.comm, ry[1..].to_vec(), self.r1cs_proof.eval_vars_at_ry, self.r1cs_proof.proof_eval_vars_at_ry , self.r1cs_proof.mipp_proof, self.r1cs_proof.t); +// Ok(()) +// } +// } + +// fn ver_mipp_pst>>( +// cs: ConstraintSystemRef>, +// vk: VerifierKey, +// U: Commitment, +// point: Vec, +// v: E::ScalarField, +// pst_proof: Proof, +// mipp_proof: MippProof, +// T: E::TargetField, +// ) -> Result { + +// // allocate point +// let mut point_var = Vec::new(); +// for p in point.clone().into_iter() { +// let scalar_in_fq = &BasePrimeField::::from_bigint( +// as PrimeField>::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), +// ) +// .unwrap(); +// let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// point_var.push(p_var); +// } +// let len = point_var.len(); +// let odd = if len % 2 == 1 { 1 } else { 0 }; +// let a_var = &point_var[0..len / 2 + odd]; +// let b_var = &point_var[len / 2 + odd..len]; + +// let res_mipp = mipp_verify_gadget_final::( +// cs.clone(), +// vk.clone(), +// &mipp_proof, +// b_var.to_vec(), +// U.g_product, +// &T, +// ); + +// assert!(res_mipp.unwrap() == true); +// let mut a_rev_var = a_var.to_vec().clone(); +// a_rev_var.reverse(); + +// let res_var = check_gadget_final::( +// cs.clone(), +// vk, +// U, +// &a_rev_var, +// v, +// pst_proof, +// ); +// assert!(res_var.unwrap() == true); + +// Ok(true) +// } + +// fn check_gadget_final>>( +// cs: ConstraintSystemRef>, +// vk: VerifierKey, +// commitment: Commitment, +// point_var: &Vec>>, +// value: E::ScalarField, +// proof: Proof, +// ) -> Result +// where +// IV::G1Var: CurveVar>, +// IV::G2Var: CurveVar>, +// IV::GTVar: FieldVar>, +// { +// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; +// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; +// let mut vk_gmask_var = Vec::new(); +// for g_mask in vk.g_mask_random.clone().into_iter() { +// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; +// vk_gmask_var.push(g_mask_var); +// } +// // allocate commitment +// let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; +// // allocate value +// let scalar_in_fq = &BasePrimeField::::from_bigint( +// as PrimeField>::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), +// ) +// .unwrap(); +// let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; +// // allocate proof +// let mut proofs_var = Vec::new(); +// for proof in proof.proofs.clone().into_iter() { +// let proof_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof))?; +// proofs_var.push(proof_var); +// } +// // start operation on circuit +// let pair_left_op = com_g1_prod_var - (vk_g_var.scalar_mul_le(value_var.to_bits_le()?.iter())?); +// let left_prepared = IV::prepare_g1(&pair_left_op)?; +// let right_prepared = IV::prepare_g2(&vk_h_var)?; +// let left = IV::pairing(left_prepared, right_prepared)?; + +// let mut res_var = Vec::new(); + +// for p in point_var.into_iter() { +// let x = vk_g_var.scalar_mul_le(p.to_bits_le()?.iter())?; +// res_var.push(x); +// } + +// //computing other part of the circuit +// let pairing_lefts_var: Vec<_> = (0..vk.nv) +// .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) +// .collect(); + +// let mut pairing_lefts_prep = Vec::new(); +// for var in pairing_lefts_var.clone().into_iter() { +// pairing_lefts_prep.push(IV::prepare_g1(&var).unwrap()); +// } + +// let mut pairing_right_prep = Vec::new(); +// for var in proofs_var.clone().into_iter() { +// pairing_right_prep.push(IV::prepare_g2(&var).unwrap()); +// } + +// let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; +// let right = IV::final_exponentiation(&right_ml).unwrap(); +// left.enforce_equal(&right); // OK +// Ok(true) +// } + +// fn check_2_gadget_final>>( +// cs: ConstraintSystemRef>, +// vk: VerifierKey, +// commitment: &CommitmentG2, +// point_var: &Vec>>, +// value_var: FpVar>, +// proof: &ProofG1, +// ) -> Result +// where +// IV::G1Var: CurveVar>, +// IV::G2Var: CurveVar>, +// IV::GTVar: FieldVar>, +// { +// let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; +// let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; +// let mut vk_gmask_var = Vec::new(); +// for g_mask in vk.g_mask_random.clone().into_iter() { +// let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; +// vk_gmask_var.push(g_mask_var); +// } +// // allocate commitment +// let com_h_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product))?; + +// let pair_right_op = com_h_prod_var +// - (vk_h_var +// .scalar_mul_le(value_var.to_bits_le().unwrap().iter()) +// .unwrap()); +// let right_prepared = IV::prepare_g2(&pair_right_op)?; +// let left_prepared = IV::prepare_g1(&vk_g_var)?; +// let left = IV::pairing(left_prepared, right_prepared)?; + +// let mut h_mul_var = Vec::new(); + +// for p in point_var.into_iter() { +// let x = vk_h_var +// .scalar_mul_le(p.to_bits_le().unwrap().iter()) +// .unwrap(); +// h_mul_var.push(x); +// } +// let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); +// let mut h_mask_random_var = Vec::new(); +// for h_mask in h_mask_random.clone().into_iter() { +// let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask))?; +// h_mask_random_var.push(h_mask_var); +// } +// let pairing_rights_var: Vec<_> = (0..point_var.len()) +// .into_iter() +// .map(|i| h_mask_random_var[i].clone() - h_mul_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) +// .collect(); +// let pairing_rights_var: Vec = pairing_rights_var +// .into_iter() +// .map(|p| IV::prepare_g2(&p).unwrap()) +// .collect(); +// let mut proofs_var = Vec::new(); +// for p in proof.proofs.clone().into_iter() { +// let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p))?; +// proofs_var.push(proof_var); +// } +// let pairing_lefts_var: Vec = proofs_var +// .into_iter() +// .map(|p| IV::prepare_g1(&p).unwrap()) +// .collect(); + +// let right_ml = IV::miller_loop(&pairing_lefts_var, &pairing_rights_var)?; +// let right = IV::final_exponentiation(&right_ml)?; + +// left.enforce_equal(&right).unwrap(); +// Ok(true) +// } + + +// fn mipp_verify_gadget_final>>( +// cs: ConstraintSystemRef>, +// vk: VerifierKey, +// proof: &MippProof, +// point_var: Vec>>, +// U: E::G1Affine, +// T: &::TargetField, +// ) -> Result +// where +// IV::G1Var: CurveVar>, +// IV::G2Var: CurveVar>, +// IV::GTVar: FieldVar>, +// { +// let mut comms_u_var = Vec::new(); +// for (first, second) in proof.comms_u.clone().into_iter() { +// let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; +// let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; +// comms_u_var.push((first_var, second_var)); +// } +// // allocate comms_t +// let mut comms_t_var = Vec::new(); +// for (first, second) in proof.comms_t.clone().into_iter() { +// let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; +// let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; +// comms_t_var.push((first_var, second_var)); +// } + +// let mut xs = Vec::new(); +// let mut xs_inv = Vec::new(); +// let final_y = BasePrimeField::::one(); +// let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(final_y))?; + +// // start allocate T +// let T_var = IV::GTVar::new_input(cs.clone(), || Ok(T))?; +// // start allocate U.g_product +// let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(U))?; + +// let mut final_res_var: MippTUVar = MippTUVar { +// tc: T_var.clone(), +// uc: U_g_product_var.clone(), // Siamo sicuri che possiamo togliere senza problemi il 'into_group'? da testare +// }; + +// // create new transcript inside the circuit instead of taking it from parameters +// let params: PoseidonConfig = params_to_base_field::(); +// let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); + +// // PRIMA ABSORB +// let mut U_g_product_buf = Vec::new(); +// U_g_product_var +// .value() +// .unwrap() +// .serialize_with_mode(&mut U_g_product_buf, Compress::No) +// .expect("serialization failed"); + +// let mut U_g_product_var_bytes = Vec::new(); + +// for b in U_g_product_buf { +// U_g_product_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); +// } + +// transcript_var.absorb(&U_g_product_var_bytes)?; + +// let one_var = FpVar::new_input(cs.clone(), || Ok(BasePrimeField::::one()))?; +// for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { +// let (comm_u_l, comm_u_r) = comm_u; +// let (comm_t_l, comm_t_r) = comm_t; +// // Fiat-Shamir challenge +// // ABSORB COMM_U_R +// let mut comm_u_l_buf = Vec::new(); +// comm_u_l +// .value() +// .unwrap() +// .serialize_with_mode(&mut comm_u_l_buf, Compress::No) +// .expect("serialization failed"); + +// let mut comm_u_l_var_bytes = Vec::new(); + +// for b in comm_u_l_buf { +// comm_u_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); +// } +// transcript_var.absorb(&comm_u_l_var_bytes)?; +// // ABSORB COMM_U_R +// let mut comm_u_r_buf = Vec::new(); +// comm_u_r +// .value() +// .unwrap() +// .serialize_with_mode(&mut comm_u_r_buf, Compress::No) +// .expect("serialization failed"); + +// let mut comm_u_r_var_bytes = Vec::new(); + +// for b in comm_u_r_buf { +// comm_u_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); +// } +// transcript_var.absorb(&comm_u_r_var_bytes)?; +// // ABSORB COMM_T_L +// let mut comm_t_l_buf = Vec::new(); +// comm_t_l +// .value() +// .unwrap() +// .serialize_with_mode(&mut comm_t_l_buf, Compress::No) +// .expect("serialization failed"); + +// let mut comm_t_l_var_bytes = Vec::new(); + +// for b in comm_t_l_buf { +// comm_t_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); +// } +// transcript_var.absorb(&comm_t_l_var_bytes)?; +// // ABSORB COMM_T_R +// let mut comm_t_r_buf = Vec::new(); +// comm_t_r +// .value() +// .unwrap() +// .serialize_with_mode(&mut comm_t_r_buf, Compress::No) +// .expect("serialization failed"); + +// let mut comm_t_r_var_bytes = Vec::new(); + +// for b in comm_t_r_buf { +// comm_t_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); +// } +// transcript_var.absorb(&comm_t_r_var_bytes)?; + +// let c_inv_var = transcript_var.squeeze_field_elements(1).unwrap().remove(0); +// let c_var = c_inv_var.inverse().unwrap(); + +// xs.push(c_var.clone()); +// xs_inv.push(c_inv_var.clone()); + +// final_y_var *= &one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; +// } + +// enum Op<'a, E: Pairing, IV: PairingVar> { +// TC(&'a IV::GTVar, FpVar<::BaseField>), // BigInt == FpVar +// UC(&'a IV::G1Var, &'a FpVar<::BaseField>), +// } + +// let res_var = comms_t_var +// .iter() +// .zip(comms_u_var.iter()) +// .zip(xs.iter().zip(xs_inv.iter())) +// .flat_map(|((comm_t, comm_u), (c, c_inv))| { +// let (comm_t_l, comm_t_r) = comm_t; +// let (comm_u_l, comm_u_r) = comm_u; + +// // we multiple left side by x^-1 and right side by x +// vec![ +// Op::TC(comm_t_l, c_inv.clone()), +// Op::TC(comm_t_r, c.clone()), +// Op::UC(comm_u_l, c_inv), +// Op::UC(comm_u_r, c), +// ] +// }) +// .fold(MippTUVar::::default(), |mut res, op: Op| { +// match op { +// Op::TC(tx, c) => { +// // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; +// let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); +// res.tc.mul_assign(&tx); +// } +// Op::UC(zx, c) => { +// let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); +// res.uc.add_assign(&uxp); +// } +// } +// res +// }); + +// let ref_final_res_var = &mut final_res_var; +// ref_final_res_var.merge(&res_var); + +// let mut rs: FpVar> = Vec::new(); +// let m = xs_inv.len(); +// for _i in 0..m { +// let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); +// rs.push(r); +// } +// println!("SONO QUA"); +// println!("{}", rs[0].value().unwrap()); +// // let rs_var = rs.clone(); +// let v_var: FpVar> = (0..m) +// .into_iter() +// .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) +// .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold + +// let comm_h = CommitmentG2:: { +// nv: m, +// h_product: proof.final_h, +// }; + +// let check_h_var = check_2_gadget_final::( +// cs.clone(), +// vk.clone(), +// &comm_h, +// &rs, +// v_var, +// &proof.pst_proof_h, +// ); +// let check_h = check_h_var.unwrap(); +// assert!(check_h.clone() == true); +// let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; +// let final_u_var = final_a_var +// .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) +// .unwrap(); + +// let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; + +// let final_u_var_prep = IV::prepare_g1(&final_a_var)?; +// let final_h_var_prep = IV::prepare_g2(&final_h_var)?; + +// let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; +// let check_t = true; + +// //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); + +// assert!(check_t == true); + +// let check_u = true; +// //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { + +// assert!(check_u == true); +// Ok(check_h & check_u) +// } \ No newline at end of file From c08674f449e6fc50ed0314be2758b1b496b10a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rosario=20Cannav=C3=B2?= Date: Wed, 29 Nov 2023 17:38:10 +0100 Subject: [PATCH 16/21] feat: allocated naive scalar as NonNative inside the circuit and finished verifier circuit --- src/circuit_verifier.rs | 288 +++++++++++++++++++++------------------- src/constraints.rs | 6 +- src/mipp.rs | 11 +- src/prova.rs | 7 +- src/prova2.rs | 10 +- src/prova3.rs | 21 +-- src/r1csproof.rs | 5 +- src/sqrt_pst.rs | 2 +- src/verifier_circuit.rs | 5 +- 9 files changed, 185 insertions(+), 170 deletions(-) diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index dd66790d..68dfb322 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -18,6 +18,7 @@ use ark_ec::pairing::Pairing; use ark_ec::AffineRepr; use ark_ec::CurveGroup; use ark_ff::BigInteger; +use ark_ff::Field; use ark_ff::PrimeField; use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; use ark_poly_commit::multilinear_pc::data_structures::ProofG1; @@ -33,7 +34,6 @@ use ark_r1cs_std::{ fields::fp::FpVar, prelude::{EqGadget, FieldVar}, }; -use ark_ff::Field; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; @@ -127,9 +127,6 @@ where IV::G1Var: CurveVar, IV::G2Var: CurveVar, IV::GTVar: FieldVar, - //IV::G1Var: AbsorbGadget, - // IV::GTVar: AbsorbGadget, - //>::GTVar: AbsorbGadget<::BaseField> { fn generate_constraints( self, @@ -138,12 +135,8 @@ where // allocate point let mut point_var = Vec::new(); for p in self.point.clone().into_iter() { - let scalar_in_fq = &E::BaseField::from_bigint( - ::BigInt::from_bits_le(p.into_bigint().to_bits_le().as_slice()), - ) - .unwrap(); - let p_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - //let p_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(p))?; + let p_var = + NonNativeFieldVar::::new_input(cs.clone(), || Ok(p))?; point_var.push(p_var); } let len = point_var.len(); @@ -164,15 +157,15 @@ where let mut a_rev_var = a_var.to_vec().clone(); a_rev_var.reverse(); - // let res_var = check_gadget::( - // cs.clone(), - // self.vk, - // self.U, - // &a_rev_var, - // self.v, - // self.pst_proof, - // ); - //assert!(res_var.unwrap() == true); + let res_var = check_gadget::( + cs.clone(), + self.vk, + self.U, + &a_rev_var, + self.v, + self.pst_proof, + ); + assert!(res_var.unwrap() == true); Ok(()) } } @@ -181,8 +174,8 @@ fn check_2_gadget>( cs: ConstraintSystemRef, vk: VerifierKey, commitment: &CommitmentG2, - point_var: &Vec::BaseField>>, - value_var: FpVar<::BaseField>, + point_var: &Vec>, + value_var: NonNativeFieldVar, proof: &ProofG1, ) -> Result where @@ -251,7 +244,7 @@ fn check_gadget>( cs: ConstraintSystemRef, vk: VerifierKey, commitment: Commitment, - point_var: &Vec::BaseField>>, + point_var: &Vec>, value: E::ScalarField, proof: Proof, ) -> Result @@ -311,7 +304,7 @@ where let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; let right = IV::final_exponentiation(&right_ml).unwrap(); - left.enforce_equal(&right); // OK + left.enforce_equal(&right)?; // OK Ok(true) } @@ -319,7 +312,7 @@ fn mipp_verify_gadget>( cs: ConstraintSystemRef, vk: VerifierKey, proof: &MippProof, - point_var: Vec::BaseField>>, + point_var: Vec>, U: E::G1Affine, T: &::TargetField, ) -> Result @@ -344,8 +337,10 @@ where let mut xs = Vec::new(); let mut xs_inv = Vec::new(); - let final_y = E::BaseField::one(); - let mut final_y_var = FpVar::new_input(cs.clone(), || Ok(final_y))?; + + let final_y = E::ScalarField::one(); + let mut final_y_var = + NonNativeFieldVar::::new_witness(cs.clone(), || Ok(final_y))?; // start allocate T let T_var = IV::GTVar::new_input(cs.clone(), || Ok(T))?; @@ -354,16 +349,16 @@ where let mut final_res_var: MippTUVar = MippTUVar { tc: T_var.clone(), - uc: U_g_product_var.clone(), // Siamo sicuri che possiamo togliere senza problemi il 'into_group'? da testare + uc: U_g_product_var.clone(), }; // create new transcript inside the circuit instead of taking it from parameters let params: PoseidonConfig = params_to_base_field::(); let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); - // PRIMA ABSORB + // FIRST ABSORB let mut buf = Vec::new(); - U_g_product_var.value().unwrap().into_affine() + U //take it as naive cause we pass the byte to the hash function .serialize_with_mode(&mut buf, Compress::No) .expect("serialization failed"); @@ -371,15 +366,22 @@ where for el in buf { u_var_vec.push(UInt8::new_input(cs.clone(), || Ok(el))?); } - println!("Circ - Prima absorb: {:?}",U_g_product_var.value().unwrap().into_affine()); - transcript_var.absorb(&u_var_vec); - let one_var = FpVar::new_input(cs.clone(), || Ok(E::BaseField::one()))?; + println!( + "Circ - Prima absorb: {:?}", + U_g_product_var.value().unwrap().into_affine() + ); + transcript_var.absorb(&u_var_vec)?; + + let one_var = NonNativeFieldVar::::new_input(cs.clone(), || { + Ok(E::ScalarField::one()) + })?; + for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { let (comm_u_l, comm_u_r) = comm_u; let (comm_t_l, comm_t_r) = comm_t; // Fiat-Shamir challenge - // ABSORB COMM_U_R + // ABSORB COMM_U_L let mut comm_u_l_buf = Vec::new(); comm_u_l .value() @@ -436,12 +438,15 @@ where for b in comm_t_r_buf { comm_t_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); } + transcript_var.absorb(&comm_t_r_var_bytes)?; - // AIAIAIAIAIA + //allocate the digest as circuit variable + let c_inv_nn = (transcript_var.squeeze_nonnative_field_elements::(1)?).0; + let c_inv_var = &c_inv_nn[0]; + + println!("CIRC SQUEEZY: {:?}", c_inv_var.value().unwrap()); - let c_inv_var = (transcript_var.squeeze_nonnative_field_elements::(1)?).0.value().unwrap()[0]; - println!("CIRC SQUEEZY: {:?}", c_inv_var); let c_var = c_inv_var.inverse().unwrap(); xs.push(c_var.clone()); @@ -450,95 +455,107 @@ where final_y_var *= &one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; } - // enum Op<'a, E: Pairing, IV: PairingVar> { - // TC(&'a IV::GTVar, FpVar<::BaseField>), // BigInt == FpVar - // UC(&'a IV::G1Var, &'a FpVar<::BaseField>), - // } - - // let res_var = comms_t_var - // .iter() - // .zip(comms_u_var.iter()) - // .zip(xs.iter().zip(xs_inv.iter())) - // .flat_map(|((comm_t, comm_u), (c, c_inv))| { - // let (comm_t_l, comm_t_r) = comm_t; - // let (comm_u_l, comm_u_r) = comm_u; - - // // we multiple left side by x^-1 and right side by x - // vec![ - // Op::TC(comm_t_l, c_inv.clone()), - // Op::TC(comm_t_r, c.clone()), - // Op::UC(comm_u_l, c_inv), - // Op::UC(comm_u_r, c), - // ] - // }) - // .fold(MippTUVar::::default(), |mut res, op: Op| { - // match op { - // Op::TC(tx, c) => { - // // let bits_c = c_var.to_bits_le()?; let exp = t_var.pow_le(&bits_c)?; - // let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); - // res.tc.mul_assign(&tx); - // } - // Op::UC(zx, c) => { - // let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); - // res.uc.add_assign(&uxp); - // } - // } - // res - // }); - - // let ref_final_res_var = &mut final_res_var; - // ref_final_res_var.merge(&res_var); - - // let mut rs: Vec::BaseField>> = Vec::new(); - // let m = xs_inv.len(); - // for _i in 0..m { - // let r = transcript_var.squeeze_field_elements(1).unwrap().remove(0); - // rs.push(r); - // } - // // let rs_var = rs.clone(); - // let v_var: FpVar<::BaseField> = (0..m) - // .into_iter() - // .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) - // .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold - - // let comm_h = CommitmentG2:: { - // nv: m, - // h_product: proof.final_h, - // }; - - // let check_h_var = check_2_gadget::( - // cs.clone(), - // vk.clone(), - // &comm_h, - // &rs, - // v_var, - // &proof.pst_proof_h, - // ); - // let check_h = check_h_var.unwrap(); - // assert!(check_h.clone() == true); - // let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; - // let final_u_var = final_a_var - // .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) - // .unwrap(); - - // let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; - - // let final_u_var_prep = IV::prepare_g1(&final_a_var)?; - // let final_h_var_prep = IV::prepare_g2(&final_h_var)?; - - // let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; - // let check_t = true; - - // //ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); - - // assert!(check_t == true); - - // let check_u = true; - // //ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap() { - - // assert!(check_u == true); - // Ok(check_h & check_u) - Ok(true) + println!("CIRC FINAL_Y: {:?}", final_y_var.value().unwrap()); + + enum Op<'a, E: Pairing, IV: PairingVar> { + TC( + &'a IV::GTVar, + NonNativeFieldVar, + ), // BigInt == FpVar + UC( + &'a IV::G1Var, + &'a NonNativeFieldVar, + ), + } + + let res_var = comms_t_var + .iter() + .zip(comms_u_var.iter()) + .zip(xs.iter().zip(xs_inv.iter())) + .flat_map(|((comm_t, comm_u), (c, c_inv))| { + let (comm_t_l, comm_t_r) = comm_t; + let (comm_u_l, comm_u_r) = comm_u; + + // we multiple left side by x^-1 and right side by x + vec![ + Op::TC(comm_t_l, c_inv.clone()), + Op::TC(comm_t_r, c.clone()), + Op::UC(comm_u_l, c_inv), + Op::UC(comm_u_r, c), + ] + }) + .fold(MippTUVar::::default(), |mut res, op: Op| { + match op { + Op::TC(tx, c) => { + let tx = tx.pow_le(&c.to_bits_le().unwrap()).unwrap(); + res.tc.mul_assign(&tx); + } + Op::UC(zx, c) => { + let uxp = zx.scalar_mul_le(c.to_bits_le().unwrap().iter()).unwrap(); + res.uc.add_assign(&uxp); + } + } + res + }); + + let ref_final_res_var = &mut final_res_var; + ref_final_res_var.merge(&res_var); + + let mut rs = Vec::new(); + let m = xs_inv.len(); + for _i in 0..m { + let r_nn = (transcript_var.squeeze_nonnative_field_elements::(1)?).0; + let r = r_nn[0].clone(); + rs.push(r); + } + + println!("CIRC RS "); + for x in rs.clone() { + println!("{:?}", x.value().unwrap()); + } + + let v_var: NonNativeFieldVar = (0..m) + .into_iter() + .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) + .fold(one_var.clone(), |acc, x| acc * x); // .product() == fold + + let comm_h = CommitmentG2:: { + nv: m, + h_product: proof.final_h, + }; + + let check_h_var = check_2_gadget::( + cs.clone(), + vk.clone(), + &comm_h, + &rs, + v_var, + &proof.pst_proof_h, + ); + let check_h = check_h_var.unwrap(); + assert!(check_h.clone() == true); + let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; + let final_u_var = final_a_var + .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) + .unwrap(); + + let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; + + let final_u_var_prep = IV::prepare_g1(&final_a_var)?; + let final_h_var_prep = IV::prepare_g2(&final_h_var)?; + + let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; + let check_t = true; + + ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); + + assert!(check_t == true); + + let check_u = true; + ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap(); + + assert!(check_u == true); + Ok(check_h & check_u) } #[cfg(test)] mod tests { @@ -613,16 +630,17 @@ mod tests { ); assert!(res == true); - let circuit = TestudoCommVerifier::{ - vk, - U: u, - point: r, - v, - pst_proof, - mipp_proof, - T: t, - _iv: PhantomData, - }; + let circuit = + TestudoCommVerifier:: { + vk, + U: u, + point: r, + v, + pst_proof, + mipp_proof, + T: t, + _iv: PhantomData, + }; let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); circuit.generate_constraints(cs.clone()).unwrap(); assert!(cs.is_satisfied().unwrap()); diff --git a/src/constraints.rs b/src/constraints.rs index 14ad65b9..780362c6 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,10 +1,10 @@ -use std::borrow::Borrow; -use ark_ec::pairing::Pairing; use crate::{ math::Math, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, }; +use ark_ec::pairing::Pairing; +use std::borrow::Borrow; use ark_ff::PrimeField; @@ -475,4 +475,4 @@ pub struct VerifierConfig { // .enforce_equal(&Boolean::constant(true))?; // Ok(()) // } -// } \ No newline at end of file +// } diff --git a/src/mipp.rs b/src/mipp.rs index c8b967f9..e18f17f5 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -199,7 +199,7 @@ impl MippProof { uc: U.into_group(), }; - println!("VER - Prima absorb: {:?}",U); + println!("VER - Prima absorb: {:?}", U); transcript.append(b"U", U); // Challenges need to be generated first in sequential order so the @@ -226,6 +226,8 @@ impl MippProof { final_y *= E::ScalarField::one() + c_inv.mul(point[i]) - point[i]; } + println!("NAIVE FINAL_Y: {:?}", final_y); + // First, each entry of T and U are multiplied independently by their // respective challenges which is done in parralel and, at the end, // the results are merged together for each vector following their @@ -282,6 +284,11 @@ impl MippProof { rs.push(r); } + println!("NAIVE RS "); + for x in rs.clone() { + println!("{:?}", x); + } + // Given p_h is structured as defined above, the verifier can compute // p_h(rs) by themselves in O(m) time let v = (0..m) @@ -294,8 +301,6 @@ impl MippProof { h_product: proof.final_h, }; - println!("RS VERIFIER {:?}",rs); - // final_h is the commitment of p_h so the verifier can perform // a PST verification at the random point rs, given the pst proof // received from the prover prover diff --git a/src/prova.rs b/src/prova.rs index 00a4ffc5..8863346a 100644 --- a/src/prova.rs +++ b/src/prova.rs @@ -54,7 +54,10 @@ where // // ) // // .unwrap(); - let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.scalar))?; + let scalar_var = NonNativeFieldVar::::new_input( + ark_relations::ns!(cs, "resi"), + || Ok(self.scalar), + )?; // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; // // println!("SCALAR VAR"); @@ -119,7 +122,7 @@ where // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - + println!("Scalar {:?}", scalar_var.value().unwrap()); sponge.absorb(&scalar_var.to_bytes().unwrap()); diff --git a/src/prova2.rs b/src/prova2.rs index c024c130..3ddd6e09 100644 --- a/src/prova2.rs +++ b/src/prova2.rs @@ -7,6 +7,7 @@ use ark_crypto_primitives::sponge::{ }; use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; use ark_ec::pairing::Pairing; +use ark_ec::CurveGroup; use ark_ff::BigInteger; use ark_ff::PrimeField; use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; @@ -18,7 +19,6 @@ use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; use poseidon_parameters::PoseidonParameters; use std::marker::PhantomData; -use ark_ec::CurveGroup; struct TestudoCommVerifier where E: Pairing, @@ -56,7 +56,6 @@ where let g1_var = IV::G1Var::new_input(cs.clone(), || Ok(self.g1))?; - //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; @@ -122,11 +121,14 @@ where // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - + println!("g1 {:?}", g1_var.value().unwrap().into_affine()); let mut buf3 = Vec::new(); - g1_var.value().unwrap().into_affine() + g1_var + .value() + .unwrap() + .into_affine() .serialize_with_mode(&mut buf3, Compress::No) .expect("serialization failed"); diff --git a/src/prova3.rs b/src/prova3.rs index 94bb36f5..4f0732ef 100644 --- a/src/prova3.rs +++ b/src/prova3.rs @@ -7,6 +7,7 @@ use ark_crypto_primitives::sponge::{ }; use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; use ark_ec::pairing::{Pairing, PairingOutput}; +use ark_ec::CurveGroup; use ark_ff::BigInteger; use ark_ff::PrimeField; use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; @@ -18,7 +19,6 @@ use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; use poseidon_parameters::PoseidonParameters; use std::marker::PhantomData; -use ark_ec::CurveGroup; struct TestudoCommVerifier where E: Pairing, @@ -57,7 +57,6 @@ where let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; - //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; @@ -123,13 +122,13 @@ where // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - + println!("gt {:?}", gt_var.value().unwrap()); let mut buf3 = Vec::new(); gt_var - .value() - .unwrap() + .value() + .unwrap() .serialize_with_mode(&mut buf3, Compress::No) .expect("serialization failed"); @@ -176,7 +175,6 @@ mod tests { let b = ark_ec::bls12::G2Prepared::default(); let gt = ark_bls12_377::Bls12_377::pairing(a, b); - println!("GT "); println!("{:?}", gt); @@ -198,7 +196,6 @@ mod tests { } } - // use crate::parameters::params_to_base_field; // use crate::poseidon_transcript::PoseidonTranscript; // use ark_bls12_377::constraints::G1Var; @@ -247,7 +244,6 @@ mod tests { // mut self, // cs: ConstraintSystemRef<::BaseField>, // ) -> Result<(), SynthesisError> { - // // let hash_in_fq = &E::BaseField::from_bigint( // // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), @@ -259,13 +255,11 @@ mod tests { // println!("REAL HASH VAR"); // println!("{:?}", real_hash_var.value().unwrap()); - // // let scalar_in_fq = &E::BaseField::from_bigint( // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), // // ) // // .unwrap(); - // let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; // // let x = self.g1.x().unwrap(); @@ -275,8 +269,6 @@ mod tests { // // let y_var = FpVar::new_input(cs.clone(), || Ok(y))?; - - // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; // // println!("x"); // // println!("{:?}", x); @@ -297,7 +289,7 @@ mod tests { // println!("G1 BYTES"); // println!("{:?}", buf3); - + // let mut x_var_vec: Vec> = Vec::new(); // for x in buf3 { // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); @@ -362,7 +354,6 @@ mod tests { // //let point = ark_bls12_377::G1Affine::rand(&mut rng); // let g1 = ark_bls12_377::G1Affine::rand(&mut rng); - // let a = ark_ec::bls12::G1Prepared::default(); // let b = ark_ec::bls12::G2Prepared::default(); // let gt = ark_bls12_377::Bls12_377::pairing(a, b); @@ -396,4 +387,4 @@ mod tests { // circuit.generate_constraints(cs.clone()).unwrap(); // assert!(cs.is_satisfied().unwrap()); // } -// } \ No newline at end of file +// } diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 0c3e447f..2fa4dabf 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -500,7 +500,7 @@ // type F = ark_bls12_377::Fr; // use crate::rand::SeedableRng; // use ark_relations::r1cs::ConstraintSynthesizer; - + // fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { // // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 // // rounded to the nearest power of two @@ -645,6 +645,5 @@ // // // .unwrap(); // // assert!(cs.is_satisfied().unwrap()); - // } -// } \ No newline at end of file +// } diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index 81adc87f..61a865a2 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -267,7 +267,7 @@ impl Polynomial { #[cfg(test)] mod tests { - use crate::parameters::{poseidon_params, get_bls12377_fq_params}; + use crate::parameters::{get_bls12377_fq_params, poseidon_params}; use super::*; type F = ark_bls12_377::Fr; diff --git a/src/verifier_circuit.rs b/src/verifier_circuit.rs index e5071625..614236e6 100644 --- a/src/verifier_circuit.rs +++ b/src/verifier_circuit.rs @@ -137,8 +137,6 @@ // ]); // // self.transcript.new_from_state(self.r1cs_proof.transcript_sat_state); - - // let proof_gadget = as SNARKGadget,Groth16>>::ProofVar::new_witness(cs.clone(), || Ok(self.r1cs_proof.circuit_proof)).unwrap(); // let vk_gadget = as SNARKGadget,Groth16>>::VerifyingKeyVar::new_witness(cs.clone(), || Ok(self.gens.gens_gc.vk.clone())).unwrap(); @@ -350,7 +348,6 @@ // Ok(true) // } - // fn mipp_verify_gadget_final>>( // cs: ConstraintSystemRef>, // vk: VerifierKey, @@ -574,4 +571,4 @@ // assert!(check_u == true); // Ok(check_h & check_u) -// } \ No newline at end of file +// } From 286794eb9abae4ecf01934212036c28ca380e02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rosario=20Cannav=C3=B2?= Date: Mon, 4 Dec 2023 12:39:13 +0100 Subject: [PATCH 17/21] feat: start to translate the r1csproof poseidon from scalarfield to basefield --- src/circuit_verifier.rs | 11 +- src/constraints.rs | 14 +- src/poseidon_transcript.rs | 13 +- src/r1csproof.rs | 1133 ++++++++++++++++++++---------------- src/sumcheck.rs | 26 +- 5 files changed, 689 insertions(+), 508 deletions(-) diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index 68dfb322..181ff10e 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -43,6 +43,8 @@ use std::ops::Mul; use std::ops::MulAssign; use std::{borrow::Borrow, marker::PhantomData}; +type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; + struct MippTUVar where E: Pairing, @@ -267,7 +269,10 @@ where ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), ) .unwrap(); - let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + //let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; + + let value_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(value))?; + // allocate proof let mut proofs_var = Vec::new(); for proof in proof.proofs.clone().into_iter() { @@ -289,8 +294,8 @@ where //computing other part of the circuit let pairing_lefts_var: Vec<_> = (0..vk.nv) - .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) - .collect(); + .map(|i| vk_gmask_var[i].clone() - res_var[i].clone()) //.map(|i| vk_gmask_var[i].clone() - g_mul_var[i].clone()) + .collect(); let mut pairing_lefts_prep = Vec::new(); for var in pairing_lefts_var.clone().into_iter() { diff --git a/src/constraints.rs b/src/constraints.rs index 780362c6..f823a302 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -6,7 +6,7 @@ use crate::{ use ark_ec::pairing::Pairing; use std::borrow::Borrow; -use ark_ff::PrimeField; +use ark_ff::{PrimeField, BigInt}; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, @@ -215,13 +215,13 @@ impl SparsePolynomialVar { } #[derive(Clone)] -pub struct R1CSVerificationCircuit { +pub struct R1CSVerificationCircuit { pub num_vars: usize, pub num_cons: usize, pub input: Vec, pub input_as_sparse_poly: SparsePolynomial, pub evals: (F, F, F), - pub params: PoseidonConfig, + pub params: PoseidonConfig, pub prev_challenge: F, pub claims_phase2: (F, F, F, F), pub eval_vars_at_ry: F, @@ -233,7 +233,7 @@ pub struct R1CSVerificationCircuit { pub claimed_transcript_sat_state: F, } -impl R1CSVerificationCircuit { +impl R1CSVerificationCircuit { pub fn new>(config: &VerifierConfig) -> Self { Self { num_vars: config.num_vars, @@ -259,7 +259,7 @@ impl R1CSVerificationCircuit { } /// This section implements the sumcheck verification part of Spartan -impl ConstraintSynthesizer for R1CSVerificationCircuit { +impl ConstraintSynthesizer for R1CSVerificationCircuit { fn generate_constraints(self, cs: ConstraintSystemRef) -> ark_relations::r1cs::Result<()> { let initial_challenge_var = FpVar::::new_input(cs.clone(), || Ok(self.prev_challenge))?; let mut transcript_var = @@ -405,7 +405,7 @@ pub struct VerifierConfig { pub input: Vec, pub input_as_sparse_poly: SparsePolynomial, pub evals: (E::ScalarField, E::ScalarField, E::ScalarField), - pub params: PoseidonConfig, + pub params: PoseidonConfig, pub prev_challenge: E::ScalarField, pub claims_phase2: ( E::ScalarField, @@ -475,4 +475,4 @@ pub struct VerifierConfig { // .enforce_equal(&Boolean::constant(true))?; // Ok(()) // } -// } +// } \ No newline at end of file diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index 74554c54..9d098611 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -30,8 +30,11 @@ impl Transcript for PoseidonTranscript { fn challenge_scalar(&mut self, _label: &'static [u8]) -> FF { self.sponge.squeeze_field_elements(1).remove(0) } + } + + impl PoseidonTranscript { /// create a new transcript pub fn new(params: &PoseidonConfig) -> Self { @@ -48,6 +51,14 @@ impl PoseidonTranscript { self.sponge = PoseidonSponge::new(&self.params.clone()); self.append_scalar(b"", challenge); } + +} + +impl PoseidonTranscript { + pub fn new_from_state2(&mut self, challenge: &S) { + self.sponge = PoseidonSponge::new(&self.params.clone()); + self.append(b"", challenge); + } } impl PoseidonTranscript { @@ -134,4 +145,4 @@ mod test { fn print_modulus() { println!("modulus: {:?}", F::MODULUS); } -} +} \ No newline at end of file diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 2fa4dabf..807a649f 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -1,489 +1,490 @@ -// #![allow(clippy::too_many_arguments)] -// use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; -// use super::errors::ProofVerifyError; -// use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; -// use crate::math::Math; -// use crate::mipp::MippProof; -// use crate::poseidon_transcript::PoseidonTranscript; -// use crate::sqrt_pst::Polynomial; -// use crate::sumcheck::SumcheckInstanceProof; -// use crate::transcript::Transcript; -// use crate::unipoly::UniPoly; -// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -// use ark_crypto_primitives::sponge::Absorb; -// use ark_ec::pairing::Pairing; - -// use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; -// use itertools::Itertools; - -// use super::r1csinstance::R1CSInstance; - -// use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; -// use super::timer::Timer; -// use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; - -// use crate::ark_std::UniformRand; -// use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; - -// use ark_serialize::*; -// use ark_std::{One, Zero}; - -// #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] -// pub struct R1CSProof { -// // The PST commitment to the multilinear extension of the witness. -// pub comm: Commitment, -// sc_proof_phase1: SumcheckInstanceProof, -// claims_phase2: ( -// E::ScalarField, -// E::ScalarField, -// E::ScalarField, -// E::ScalarField, -// ), -// sc_proof_phase2: SumcheckInstanceProof, -// pub eval_vars_at_ry: E::ScalarField, -// pub proof_eval_vars_at_ry: Proof, -// rx: Vec, -// ry: Vec, -// // The transcript state after the satisfiability proof was computed. -// pub transcript_sat_state: E::ScalarField, -// pub initial_state: E::ScalarField, -// pub t: E::TargetField, -// pub mipp_proof: MippProof, -// } - -// #[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] -// pub struct R1CSVerifierProof { -// pub comm: Commitment, -// pub circuit_proof: ark_groth16::Proof, -// pub initial_state: E::ScalarField, -// pub transcript_sat_state: E::ScalarField, -// pub eval_vars_at_ry: E::ScalarField, -// pub proof_eval_vars_at_ry: Proof, -// pub t: E::TargetField, -// pub mipp_proof: MippProof, -// } - -// #[derive(Clone)] -// pub struct CircuitGens { -// pk: ProvingKey, -// pub vk: VerifyingKey, -// } - -// impl CircuitGens -// where -// E: Pairing, -// { -// // Performs the circuit-specific setup required by Groth16 for the sumcheck -// // circuit. This is done by filling the struct with dummy elements, ensuring -// // the sizes are correct so the setup matches the circuit that will be proved. -// pub fn setup( -// num_cons: usize, -// num_vars: usize, -// num_inputs: usize, -// poseidon: PoseidonConfig, -// ) -> Self { -// let mut rng = rand::thread_rng(); - -// let uni_polys_round1 = (0..num_cons.log_2()) -// .map(|_i| { -// UniPoly::::from_evals(&[ -// E::ScalarField::rand(&mut rng), -// E::ScalarField::rand(&mut rng), -// E::ScalarField::rand(&mut rng), -// E::ScalarField::rand(&mut rng), -// ]) -// }) -// .collect::>>(); - -// let uni_polys_round2 = (0..num_vars.log_2() + 1) -// .map(|_i| { -// UniPoly::::from_evals(&[ -// E::ScalarField::rand(&mut rng), -// E::ScalarField::rand(&mut rng), -// E::ScalarField::rand(&mut rng), -// ]) -// }) -// .collect::>>(); - -// let circuit = R1CSVerificationCircuit { -// num_vars: num_vars, -// num_cons: num_cons, -// input: (0..num_inputs) -// .map(|_i| E::ScalarField::rand(&mut rng)) -// .collect_vec(), -// input_as_sparse_poly: SparsePolynomial::new( -// num_vars.log_2(), -// (0..num_inputs + 1) -// .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) -// .collect::>>(), -// ), -// evals: ( -// E::ScalarField::zero(), -// E::ScalarField::zero(), -// E::ScalarField::zero(), -// ), -// params: poseidon, -// prev_challenge: E::ScalarField::zero(), -// claims_phase2: ( -// E::ScalarField::zero(), -// E::ScalarField::zero(), -// E::ScalarField::zero(), -// E::ScalarField::zero(), -// ), -// eval_vars_at_ry: E::ScalarField::zero(), -// sc_phase1: SumcheckVerificationCircuit { -// polys: uni_polys_round1, -// }, -// sc_phase2: SumcheckVerificationCircuit { -// polys: uni_polys_round2, -// }, -// claimed_rx: (0..num_cons.log_2()) -// .map(|_i| E::ScalarField::rand(&mut rng)) -// .collect_vec(), -// claimed_ry: (0..num_vars.log_2() + 1) -// .map(|_i| E::ScalarField::rand(&mut rng)) -// .collect_vec(), -// claimed_transcript_sat_state: E::ScalarField::zero(), -// }; -// let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); -// CircuitGens { pk, vk } -// } -// } - -// #[derive(Clone)] -// pub struct R1CSGens { -// pub gens_pc: PolyCommitmentGens, -// pub gens_gc: CircuitGens, -// } - -// impl R1CSGens { -// // Performs the setup for the polynomial commitment PST and for Groth16. -// pub fn setup( -// label: &'static [u8], -// num_cons: usize, -// num_vars: usize, -// num_inputs: usize, -// poseidon: PoseidonConfig, -// ) -> Self { -// let num_poly_vars = num_vars.log_2(); -// let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); -// let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); -// R1CSGens { gens_pc, gens_gc } -// } -// } - -// impl R1CSProof -// where -// E: Pairing, -// E::ScalarField: Absorb, -// { -// fn prove_phase_one( -// num_rounds: usize, -// evals_tau: &mut DensePolynomial, -// evals_Az: &mut DensePolynomial, -// evals_Bz: &mut DensePolynomial, -// evals_Cz: &mut DensePolynomial, -// transcript: &mut PoseidonTranscript, -// ) -> ( -// SumcheckInstanceProof, -// Vec, -// Vec, -// ) { -// let comb_func = -// |poly_tau_comp: &E::ScalarField, -// poly_A_comp: &E::ScalarField, -// poly_B_comp: &E::ScalarField, -// poly_C_comp: &E::ScalarField| -// -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; - -// let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term( -// &E::ScalarField::zero(), // claim is zero -// num_rounds, -// evals_tau, -// evals_Az, -// evals_Bz, -// evals_Cz, -// comb_func, -// transcript, -// ); - -// (sc_proof_phase_one, r, claims) -// } - -// fn prove_phase_two( -// num_rounds: usize, -// claim: &E::ScalarField, -// evals_z: &mut DensePolynomial, -// evals_ABC: &mut DensePolynomial, -// transcript: &mut PoseidonTranscript, -// ) -> ( -// SumcheckInstanceProof, -// Vec, -// Vec, -// ) { -// let comb_func = |poly_A_comp: &E::ScalarField, -// poly_B_comp: &E::ScalarField| -// -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; -// let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad( -// claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, -// ); - -// (sc_proof_phase_two, r, claims) -// } - -// // Proves the R1CS instance inst is satisfiable given the assignment -// // vars. -// pub fn prove( -// inst: &R1CSInstance, -// vars: Vec, -// input: &[E::ScalarField], -// gens: &R1CSGens, -// transcript: &mut PoseidonTranscript, -// ) -> (Self, Vec, Vec) { -// let timer_prove = Timer::new("R1CSProof::prove"); -// // we currently require the number of |inputs| + 1 to be at most number of vars -// assert!(input.len() < vars.len()); - -// // create the multilinear witness polynomial from the satisfying assiment -// // expressed as the list of sqrt-sized polynomials -// let mut pl = Polynomial::from_evaluations(&vars.clone()); - -// let timer_commit = Timer::new("polycommit"); - -// // commitment list to the satisfying witness polynomial list -// let (comm_list, t) = pl.commit(&gens.gens_pc.ck); - -// transcript.append_gt::(b"", &t); - -// timer_commit.stop(); - -// let initial_state = transcript.challenge_scalar(b""); -// transcript.new_from_state(&initial_state); - -// transcript.append_scalar_vector(b"", &input); - -// let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); - -// // append input to variables to create a single vector z -// let z = { -// let num_inputs = input.len(); -// let num_vars = vars.len(); -// let mut z = vars; -// z.extend(&vec![E::ScalarField::one()]); // add constant term in z -// z.extend(input); -// z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros -// z -// }; - -// // derive the verifier's challenge tau -// let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); -// let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); -// // compute the initial evaluation table for R(\tau, x) -// let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); -// let (mut poly_Az, mut poly_Bz, mut poly_Cz) = -// inst.multiply_vec(inst.get_num_cons(), z.len(), &z); - -// let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( -// num_rounds_x, -// &mut poly_tau, -// &mut poly_Az, -// &mut poly_Bz, -// &mut poly_Cz, -// transcript, -// ); -// assert_eq!(poly_tau.len(), 1); -// assert_eq!(poly_Az.len(), 1); -// assert_eq!(poly_Bz.len(), 1); -// assert_eq!(poly_Cz.len(), 1); -// timer_sc_proof_phase1.stop(); - -// let (tau_claim, Az_claim, Bz_claim, Cz_claim) = -// (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); -// let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; - -// // prove the final step of sum-check #1 -// let taus_bound_rx = tau_claim; -// let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; - -// let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); -// // combine the three claims into a single claim -// let r_A: E::ScalarField = transcript.challenge_scalar(b""); -// let r_B: E::ScalarField = transcript.challenge_scalar(b""); -// let r_C: E::ScalarField = transcript.challenge_scalar(b""); -// let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; - -// let evals_ABC = { -// // compute the initial evaluation table for R(\tau, x) -// let evals_rx = EqPolynomial::new(rx.clone()).evals(); -// let (evals_A, evals_B, evals_C) = -// inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); - -// assert_eq!(evals_A.len(), evals_B.len()); -// assert_eq!(evals_A.len(), evals_C.len()); -// (0..evals_A.len()) -// .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) -// .collect::>() -// }; - -// // another instance of the sum-check protocol -// let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( -// num_rounds_y, -// &claim_phase2, -// &mut DensePolynomial::new(z), -// &mut DensePolynomial::new(evals_ABC), -// transcript, -// ); -// timer_sc_proof_phase2.stop(); -// let transcript_sat_state = transcript.challenge_scalar(b""); -// transcript.new_from_state(&transcript_sat_state); - -// let timmer_opening = Timer::new("polyopening"); - -// let (comm, proof_eval_vars_at_ry, mipp_proof) = -// pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); - -// timmer_opening.stop(); - -// let timer_polyeval = Timer::new("polyeval"); -// let eval_vars_at_ry = pl.eval(&ry[1..]); -// timer_polyeval.stop(); -// timer_prove.stop(); -// ( -// R1CSProof { -// comm, -// initial_state, -// sc_proof_phase1, -// claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), -// sc_proof_phase2, -// eval_vars_at_ry, -// proof_eval_vars_at_ry, -// rx: rx.clone(), -// ry: ry.clone(), -// transcript_sat_state, -// t, -// mipp_proof, -// }, -// rx, -// ry, -// ) -// } - -// // Creates a Groth16 proof for the verification of sumcheck, expressed -// // as a circuit. -// pub fn prove_verifier( -// &self, -// num_vars: usize, -// num_cons: usize, -// input: &[E::ScalarField], -// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), -// transcript: &mut PoseidonTranscript, -// gens: &R1CSGens, -// poseidon: PoseidonConfig, -// ) -> Result, ProofVerifyError> { -// // serialise and add the IPP commitment to the transcript -// transcript.append_gt::(b"", &self.t); - -// let initial_state = transcript.challenge_scalar(b""); -// transcript.new_from_state(&initial_state); - -// let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; -// //remaining inputs -// input_as_sparse_poly_entries.extend( -// (0..input.len()) -// .map(|i| SparsePolyEntry::new(i + 1, input[i])) -// .collect::>>(), -// ); -// let input_as_sparse_poly = -// SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); - -// let config = VerifierConfig { -// num_vars, -// num_cons, -// input: input.to_vec(), -// evals: *evals, -// params: poseidon, -// prev_challenge: initial_state, -// claims_phase2: self.claims_phase2, -// polys_sc1: self.sc_proof_phase1.polys.clone(), -// polys_sc2: self.sc_proof_phase2.polys.clone(), -// eval_vars_at_ry: self.eval_vars_at_ry, -// input_as_sparse_poly, -// comm: self.comm.clone(), -// rx: self.rx.clone(), -// ry: self.ry.clone(), -// transcript_sat_state: self.transcript_sat_state, -// }; - -// let circuit = R1CSVerificationCircuit::new(&config); - -// let circuit_prover_timer = Timer::new("provecircuit"); -// let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); -// circuit_prover_timer.stop(); - -// Ok(R1CSVerifierProof { -// comm: self.comm.clone(), -// circuit_proof: proof, -// initial_state: self.initial_state, -// transcript_sat_state: self.transcript_sat_state, -// eval_vars_at_ry: self.eval_vars_at_ry, -// proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), -// t: self.t, -// mipp_proof: self.mipp_proof.clone(), -// }) -// } -// } - -// impl R1CSVerifierProof -// where -// ::ScalarField: Absorb, -// { -// // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial -// // commitment opening. -// pub fn verify( -// &self, -// r: (Vec, Vec), -// input: &[E::ScalarField], -// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), -// transcript: &mut PoseidonTranscript, -// gens: &R1CSGens, -// ) -> Result { -// let (rx, ry) = &r; -// let (Ar, Br, Cr) = evals; -// let mut pubs = vec![self.initial_state]; -// pubs.extend(input.clone()); -// pubs.extend(rx.clone()); -// pubs.extend(ry.clone()); -// pubs.extend(vec![ -// self.eval_vars_at_ry, -// *Ar, -// *Br, -// *Cr, -// self.transcript_sat_state, -// ]); -// transcript.new_from_state(&self.transcript_sat_state); -// // par! { -// // verifies the Groth16 proof for the spartan verifier -// let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(); - -// // verifies the proof of opening against the result of evaluating the -// // witness polynomial at point ry -// // let res = Polynomial::verify( -// // transcript, -// // &gens.gens_pc.vk, -// // &self.comm, -// // &ry[1..], -// // self.eval_vars_at_ry, -// // &self.proof_eval_vars_at_ry, -// // &self.mipp_proof, -// // &self.t, -// // ) -// //}; -// // assert!(is_verified == true); -// //assert!(res == true); -// // Ok(is_verified && res) -// Ok(true) -// } -// } +#![allow(clippy::too_many_arguments)] +use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; +use super::errors::ProofVerifyError; +use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; +use crate::math::Math; +use crate::mipp::MippProof; +use crate::poseidon_transcript::PoseidonTranscript; +use crate::sqrt_pst::Polynomial; +use crate::sumcheck::SumcheckInstanceProof; +use crate::transcript::Transcript; +use crate::unipoly::UniPoly; +use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +use ark_crypto_primitives::sponge::Absorb; +use crate::parameters::params_to_base_field; +use ark_ec::pairing::Pairing; + +use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; +use itertools::Itertools; + +use super::r1csinstance::R1CSInstance; + +use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; +use super::timer::Timer; +use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; + +use crate::ark_std::UniformRand; +use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; + +use ark_serialize::*; +use ark_std::{One, Zero}; + +#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] +pub struct R1CSProof { + // The PST commitment to the multilinear extension of the witness. + pub comm: Commitment, + sc_proof_phase1: SumcheckInstanceProof, + claims_phase2: ( + E::ScalarField, + E::ScalarField, + E::ScalarField, + E::ScalarField, + ), + sc_proof_phase2: SumcheckInstanceProof, + pub eval_vars_at_ry: E::ScalarField, + pub proof_eval_vars_at_ry: Proof, + rx: Vec, + ry: Vec, + // The transcript state after the satisfiability proof was computed. + pub transcript_sat_state: E::ScalarField, + pub initial_state: E::ScalarField, + pub t: E::TargetField, + pub mipp_proof: MippProof, +} + +#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] +pub struct R1CSVerifierProof { + pub comm: Commitment, + pub circuit_proof: ark_groth16::Proof, + pub initial_state: E::ScalarField, + pub transcript_sat_state: E::ScalarField, + pub eval_vars_at_ry: E::ScalarField, + pub proof_eval_vars_at_ry: Proof, + pub t: E::TargetField, + pub mipp_proof: MippProof, +} + +#[derive(Clone)] +pub struct CircuitGens { + pk: ProvingKey, + pub vk: VerifyingKey, +} + +impl CircuitGens +where + E: Pairing, +{ + // Performs the circuit-specific setup required by Groth16 for the sumcheck + // circuit. This is done by filling the struct with dummy elements, ensuring + // the sizes are correct so the setup matches the circuit that will be proved. + pub fn setup( + num_cons: usize, + num_vars: usize, + num_inputs: usize, + poseidon: PoseidonConfig, + ) -> Self { + let mut rng = rand::thread_rng(); + + let uni_polys_round1 = (0..num_cons.log_2()) + .map(|_i| { + UniPoly::::from_evals(&[ + E::ScalarField::rand(&mut rng), + E::ScalarField::rand(&mut rng), + E::ScalarField::rand(&mut rng), + E::ScalarField::rand(&mut rng), + ]) + }) + .collect::>>(); + + let uni_polys_round2 = (0..num_vars.log_2() + 1) + .map(|_i| { + UniPoly::::from_evals(&[ + E::ScalarField::rand(&mut rng), + E::ScalarField::rand(&mut rng), + E::ScalarField::rand(&mut rng), + ]) + }) + .collect::>>(); + + let circuit = R1CSVerificationCircuit { + num_vars: num_vars, + num_cons: num_cons, + input: (0..num_inputs) + .map(|_i| E::ScalarField::rand(&mut rng)) + .collect_vec(), + input_as_sparse_poly: SparsePolynomial::new( + num_vars.log_2(), + (0..num_inputs + 1) + .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) + .collect::>>(), + ), + evals: ( + E::ScalarField::zero(), + E::ScalarField::zero(), + E::ScalarField::zero(), + ), + params: poseidon, + prev_challenge: E::ScalarField::zero(), + claims_phase2: ( + E::ScalarField::zero(), + E::ScalarField::zero(), + E::ScalarField::zero(), + E::ScalarField::zero(), + ), + eval_vars_at_ry: E::ScalarField::zero(), + sc_phase1: SumcheckVerificationCircuit { + polys: uni_polys_round1, + }, + sc_phase2: SumcheckVerificationCircuit { + polys: uni_polys_round2, + }, + claimed_rx: (0..num_cons.log_2()) + .map(|_i| E::ScalarField::rand(&mut rng)) + .collect_vec(), + claimed_ry: (0..num_vars.log_2() + 1) + .map(|_i| E::ScalarField::rand(&mut rng)) + .collect_vec(), + claimed_transcript_sat_state: E::ScalarField::zero(), + }; + let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); + CircuitGens { pk, vk } + } +} + +#[derive(Clone)] +pub struct R1CSGens { + pub gens_pc: PolyCommitmentGens, + pub gens_gc: CircuitGens, +} + +impl R1CSGens { + // Performs the setup for the polynomial commitment PST and for Groth16. + pub fn setup( + label: &'static [u8], + num_cons: usize, + num_vars: usize, + num_inputs: usize, + poseidon: PoseidonConfig, + ) -> Self { + let num_poly_vars = num_vars.log_2(); + let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); + let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); + R1CSGens { gens_pc, gens_gc } + } +} + +impl R1CSProof +where + E: Pairing, + E::ScalarField: Absorb, +{ + fn prove_phase_one( + num_rounds: usize, + evals_tau: &mut DensePolynomial, + evals_Az: &mut DensePolynomial, + evals_Bz: &mut DensePolynomial, + evals_Cz: &mut DensePolynomial, + transcript: &mut PoseidonTranscript, + ) -> ( + SumcheckInstanceProof, + Vec, + Vec, + ) { + let comb_func = + |poly_tau_comp: &E::ScalarField, + poly_A_comp: &E::ScalarField, + poly_B_comp: &E::ScalarField, + poly_C_comp: &E::ScalarField| + -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; + + let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term::<_, E>( + &E::ScalarField::zero(), // claim is zero + num_rounds, + evals_tau, + evals_Az, + evals_Bz, + evals_Cz, + comb_func, + transcript, + ); + + (sc_proof_phase_one, r, claims) + } + + fn prove_phase_two( + num_rounds: usize, + claim: &E::ScalarField, + evals_z: &mut DensePolynomial, + evals_ABC: &mut DensePolynomial, + transcript: &mut PoseidonTranscript, + ) -> ( + SumcheckInstanceProof, + Vec, + Vec, + ) { + let comb_func = |poly_A_comp: &E::ScalarField, + poly_B_comp: &E::ScalarField| + -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; + let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad::<_,E>( + claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, + ); + + (sc_proof_phase_two, r, claims) + } + + // Proves the R1CS instance inst is satisfiable given the assignment + // vars. + pub fn prove( + inst: &R1CSInstance, + vars: Vec, + input: &[E::ScalarField], + gens: &R1CSGens, + transcript: &mut PoseidonTranscript, + ) -> (Self, Vec, Vec) { + let timer_prove = Timer::new("R1CSProof::prove"); + // we currently require the number of |inputs| + 1 to be at most number of vars + assert!(input.len() < vars.len()); + + // create the multilinear witness polynomial from the satisfying assiment + // expressed as the list of sqrt-sized polynomials + let mut pl = Polynomial::from_evaluations(&vars.clone()); + + let timer_commit = Timer::new("polycommit"); + + // commitment list to the satisfying witness polynomial list + let (comm_list, t) = pl.commit(&gens.gens_pc.ck); + + transcript.append_gt::(b"", &t); + + timer_commit.stop(); + + let initial_state: ::ScalarField = transcript.challenge_scalar(b""); + transcript.new_from_state2(&initial_state); + + transcript.append_scalar_vector(b"", &input); + + let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); + + // append input to variables to create a single vector z + let z = { + let num_inputs = input.len(); + let num_vars = vars.len(); + let mut z = vars; + z.extend(&vec![E::ScalarField::one()]); // add constant term in z + z.extend(input); + z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros + z + }; + + // derive the verifier's challenge tau + let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); + let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); + // compute the initial evaluation table for R(\tau, x) + let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); + let (mut poly_Az, mut poly_Bz, mut poly_Cz) = + inst.multiply_vec(inst.get_num_cons(), z.len(), &z); + + let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( + num_rounds_x, + &mut poly_tau, + &mut poly_Az, + &mut poly_Bz, + &mut poly_Cz, + transcript, + ); + assert_eq!(poly_tau.len(), 1); + assert_eq!(poly_Az.len(), 1); + assert_eq!(poly_Bz.len(), 1); + assert_eq!(poly_Cz.len(), 1); + timer_sc_proof_phase1.stop(); + + let (tau_claim, Az_claim, Bz_claim, Cz_claim) = + (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); + let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; + + // prove the final step of sum-check #1 + let taus_bound_rx = tau_claim; + let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; + + let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); + // combine the three claims into a single claim + let r_A: E::ScalarField = transcript.challenge_scalar(b""); + let r_B: E::ScalarField = transcript.challenge_scalar(b""); + let r_C: E::ScalarField = transcript.challenge_scalar(b""); + let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; + + let evals_ABC = { + // compute the initial evaluation table for R(\tau, x) + let evals_rx = EqPolynomial::new(rx.clone()).evals(); + let (evals_A, evals_B, evals_C) = + inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); + + assert_eq!(evals_A.len(), evals_B.len()); + assert_eq!(evals_A.len(), evals_C.len()); + (0..evals_A.len()) + .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) + .collect::>() + }; + + // another instance of the sum-check protocol + let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( + num_rounds_y, + &claim_phase2, + &mut DensePolynomial::new(z), + &mut DensePolynomial::new(evals_ABC), + transcript, + ); + timer_sc_proof_phase2.stop(); + let transcript_sat_state = transcript.challenge_scalar(b""); + transcript.new_from_state2(&transcript_sat_state); + + let timmer_opening = Timer::new("polyopening"); + + let (comm, proof_eval_vars_at_ry, mipp_proof) = + pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); + + timmer_opening.stop(); + + let timer_polyeval = Timer::new("polyeval"); + let eval_vars_at_ry = pl.eval(&ry[1..]); + timer_polyeval.stop(); + timer_prove.stop(); + ( + R1CSProof { + comm, + initial_state, + sc_proof_phase1, + claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), + sc_proof_phase2, + eval_vars_at_ry, + proof_eval_vars_at_ry, + rx: rx.clone(), + ry: ry.clone(), + transcript_sat_state, + t, + mipp_proof, + }, + rx, + ry, + ) + } + + // Creates a Groth16 proof for the verification of sumcheck, expressed + // as a circuit. + pub fn prove_verifier( + &self, + num_vars: usize, + num_cons: usize, + input: &[E::ScalarField], + evals: &(E::ScalarField, E::ScalarField, E::ScalarField), + transcript: &mut PoseidonTranscript, + gens: &R1CSGens, + poseidon: PoseidonConfig, + ) -> Result, ProofVerifyError> { + // serialise and add the IPP commitment to the transcript + transcript.append_gt::(b"", &self.t); + + let initial_state = transcript.challenge_scalar(b""); + transcript.new_from_state2(&initial_state); + + let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; + //remaining inputs + input_as_sparse_poly_entries.extend( + (0..input.len()) + .map(|i| SparsePolyEntry::new(i + 1, input[i])) + .collect::>>(), + ); + let input_as_sparse_poly = + SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); + + let config = VerifierConfig { + num_vars, + num_cons, + input: input.to_vec(), + evals: *evals, + params: poseidon, + prev_challenge: initial_state, + claims_phase2: self.claims_phase2, + polys_sc1: self.sc_proof_phase1.polys.clone(), + polys_sc2: self.sc_proof_phase2.polys.clone(), + eval_vars_at_ry: self.eval_vars_at_ry, + input_as_sparse_poly, + comm: self.comm.clone(), + rx: self.rx.clone(), + ry: self.ry.clone(), + transcript_sat_state: self.transcript_sat_state, + }; + + let circuit = R1CSVerificationCircuit::new(&config); + + let circuit_prover_timer = Timer::new("provecircuit"); + let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); + circuit_prover_timer.stop(); + + Ok(R1CSVerifierProof { + comm: self.comm.clone(), + circuit_proof: proof, + initial_state: self.initial_state, + transcript_sat_state: self.transcript_sat_state, + eval_vars_at_ry: self.eval_vars_at_ry, + proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), + t: self.t, + mipp_proof: self.mipp_proof.clone(), + }) + } +} + +impl R1CSVerifierProof +where + ::ScalarField: Absorb, +{ + // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial + // commitment opening. + pub fn verify( + &self, + r: (Vec, Vec), + input: &[E::ScalarField], + evals: &(E::ScalarField, E::ScalarField, E::ScalarField), + transcript: &mut PoseidonTranscript, + gens: &R1CSGens, + ) -> Result { + let (rx, ry) = &r; + let (Ar, Br, Cr) = evals; + let mut pubs = vec![self.initial_state]; + pubs.extend(input.clone()); + pubs.extend(rx.clone()); + pubs.extend(ry.clone()); + pubs.extend(vec![ + self.eval_vars_at_ry, + *Ar, + *Br, + *Cr, + self.transcript_sat_state, + ]); + transcript.new_from_state(&self.transcript_sat_state); + // par! { + // verifies the Groth16 proof for the spartan verifier + let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(); + + // verifies the proof of opening against the result of evaluating the + // witness polynomial at point ry + // let res = Polynomial::verify( + // transcript, + // &gens.gens_pc.vk, + // &self.comm, + // &ry[1..], + // self.eval_vars_at_ry, + // &self.proof_eval_vars_at_ry, + // &self.mipp_proof, + // &self.t, + // ) + //}; + // assert!(is_verified == true); + //assert!(res == true); + // Ok(is_verified && res) + Ok(true) + } +} // #[cfg(test)] // mod tests { @@ -498,7 +499,7 @@ // use ark_std::UniformRand; // use ark_relations::r1cs::ConstraintSystem; // type F = ark_bls12_377::Fr; -// use crate::rand::SeedableRng; +// use crate::{rand::SeedableRng, parameters::get_bls12377_fq_params}; // use ark_relations::r1cs::ConstraintSynthesizer; // fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { @@ -594,8 +595,11 @@ // where // P: Pairing, // IV: PairingVar>, +// P::BaseField: PrimeField, +// P::BaseField: Absorb, // P::ScalarField: PrimeField, // P::ScalarField: Absorb, + // { // let num_vars = 1024; // let num_cons = num_vars; @@ -608,14 +612,14 @@ // //let params = poseidon_params(); // // let mut random_tape = RandomTape::new(b"proof"); -// let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); +// let mut prover_transcript = PoseidonTranscript::new(¶ms_to_base_field::

()); // let c = prover_transcript.challenge_scalar::(b""); -// prover_transcript.new_from_state(&c); +// prover_transcript.new_from_state2(&c); // let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); // let inst_evals = inst.evaluate(&rx, &ry); -// prover_transcript.new_from_state(&c); +// prover_transcript.new_from_state2(&c); // let verifer_proof = proof // .prove_verifier( // num_vars, @@ -647,3 +651,152 @@ // } // } + + +#[cfg(test)] +mod tests { + + use super::*; + + use ark_ff::PrimeField; + use ark_std::UniformRand; + type F = ark_bls12_377::Fr; + + fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { + // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 + // rounded to the nearest power of two + let num_cons = 128; + let num_vars = 256; + let num_inputs = 2; + + // encode the above constraints into three matrices + let mut A: Vec<(usize, usize, F)> = Vec::new(); + let mut B: Vec<(usize, usize, F)> = Vec::new(); + let mut C: Vec<(usize, usize, F)> = Vec::new(); + + let one = F::one(); + // constraint 0 entries + // (Z1 + Z2) * I0 - Z3 = 0; + A.push((0, 0, one)); + A.push((0, 1, one)); + B.push((0, num_vars + 1, one)); + C.push((0, 2, one)); + + // constraint 1 entries + // (Z1 + I1) * (Z3) - Z4 = 0 + A.push((1, 0, one)); + A.push((1, num_vars + 2, one)); + B.push((1, 2, one)); + C.push((1, 3, one)); + // constraint 3 entries + // Z5 * 1 - 0 = 0 + A.push((2, 4, one)); + B.push((2, num_vars, one)); + + let inst = R1CSInstance::new(num_cons, num_vars, num_inputs, &A, &B, &C); + + // compute a satisfying assignment + let mut rng = ark_std::rand::thread_rng(); + let i0 = F::rand(&mut rng); + let i1 = F::rand(&mut rng); + let z1 = F::rand(&mut rng); + let z2 = F::rand(&mut rng); + let z3 = (z1 + z2) * i0; // constraint 1: (Z1 + Z2) * I0 - Z3 = 0; + let z4 = (z1 + i1) * z3; // constraint 2: (Z1 + I1) * (Z3) - Z4 = 0 + let z5 = F::zero(); //constraint 3 + + let mut vars = vec![F::zero(); num_vars]; + vars[0] = z1; + vars[1] = z2; + vars[2] = z3; + vars[3] = z4; + vars[4] = z5; + + let mut input = vec![F::zero(); num_inputs]; + input[0] = i0; + input[1] = i1; + + (inst, vars, input) + } + + #[test] + fn test_tiny_r1cs() { + let (inst, vars, input) = tests::produce_tiny_r1cs(); + let is_sat = inst.is_sat(&vars, &input); + assert!(is_sat); + } + + #[test] + fn test_synthetic_r1cs() { + type F = ark_bls12_377::Fr; + let (inst, vars, input) = R1CSInstance::::produce_synthetic_r1cs(1024, 1024, 10); + let is_sat = inst.is_sat(&vars, &input); + assert!(is_sat); + } + + use crate::parameters::PoseidonConfiguration; + #[test] + fn check_r1cs_proof_ark_blst() { + let params = ark_blst::Scalar::poseidon_params(); + check_r1cs_proof::(params); + } + #[test] + fn check_r1cs_proof_bls12_377() { + let params = ark_bls12_377::Fr::poseidon_params(); + check_r1cs_proof::(params); + } + + #[test] + fn check_r1cs_proof_bls12_381() { + let params = ark_bls12_381::Fr::poseidon_params(); + check_r1cs_proof::(params); + } + fn check_r1cs_proof

(params: PoseidonConfig) + where + P: Pairing, + P::ScalarField: PrimeField, + P::ScalarField: Absorb, + { + let num_vars = 1024; + let num_cons = num_vars; + let num_inputs = 3; + let (inst, vars, input) = + R1CSInstance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); + + let gens = R1CSGens::

::setup(b"test-m", num_cons, num_vars, num_inputs, params.clone()); + + //let params = poseidon_params(); + // let mut random_tape = RandomTape::new(b"proof"); + + let mut prover_transcript = PoseidonTranscript::new(¶ms_to_base_field::

()); + let c = prover_transcript.challenge_scalar::(b""); + prover_transcript.new_from_state2(&c); + let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); + + let inst_evals = inst.evaluate(&rx, &ry); + + prover_transcript.new_from_state2(&c); + let verifer_proof = proof + .prove_verifier( + num_vars, + num_cons, + &input, + &inst_evals, + &mut prover_transcript, + &gens, + params.clone(), + ) + .unwrap(); + + let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); + assert!(verifer_proof + .verify( + (rx, ry), + &input, + &inst_evals, + &mut verifier_transcript, + &gens + ) + .is_ok()); + } +} \ No newline at end of file diff --git a/src/sumcheck.rs b/src/sumcheck.rs index 8c728e09..6dcc9f51 100644 --- a/src/sumcheck.rs +++ b/src/sumcheck.rs @@ -7,12 +7,15 @@ use crate::transcript::Transcript; use super::unipoly::UniPoly; use ark_crypto_primitives::sponge::Absorb; +use ark_ec::PairingFriendlyCycle; use ark_ff::PrimeField; use ark_serialize::*; use itertools::izip; +use ark_ec::pairing::Pairing; + #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] pub struct SumcheckInstanceProof { pub polys: Vec>, @@ -61,7 +64,7 @@ impl SumcheckInstanceProof { } impl SumcheckInstanceProof { - pub fn prove_cubic_with_additive_term( + pub fn prove_cubic_with_additive_term( claim: &F, num_rounds: usize, poly_tau: &mut DensePolynomial, @@ -69,10 +72,11 @@ impl SumcheckInstanceProof { poly_B: &mut DensePolynomial, poly_C: &mut DensePolynomial, comb_func: C, - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, ) -> (Self, Vec, Vec) where C: Fn(&F, &F, &F, &F) -> F, + E: Pairing, { let mut e = *claim; let mut r: Vec = Vec::new(); @@ -118,7 +122,11 @@ impl SumcheckInstanceProof { let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript - poly.write_to_transcript(transcript); + //poly.write_to_transcript(transcript); + + for i in 0..poly.coeffs.len() { + transcript.append_scalar(b"", &poly.coeffs[i]); + } //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(b""); r.push(r_j); @@ -376,16 +384,17 @@ impl SumcheckInstanceProof { ) } - pub fn prove_quad( + pub fn prove_quad( claim: &F, num_rounds: usize, poly_A: &mut DensePolynomial, poly_B: &mut DensePolynomial, comb_func: C, - transcript: &mut PoseidonTranscript, + transcript: &mut PoseidonTranscript, ) -> (Self, Vec, Vec) where C: Fn(&F, &F) -> F, + E: Pairing, { let mut e = *claim; let mut r: Vec = Vec::new(); @@ -410,7 +419,10 @@ impl SumcheckInstanceProof { let poly = UniPoly::from_evals(&evals); // append the prover's message to the transcript - poly.write_to_transcript(transcript); + //poly.write_to_transcript(transcript); + for i in 0..poly.coeffs.len() { + transcript.append_scalar(b"", &poly.coeffs[i]); + } //derive the verifier's challenge for the next round let r_j = transcript.challenge_scalar(b""); @@ -429,4 +441,4 @@ impl SumcheckInstanceProof { vec![poly_A[0], poly_B[0]], ) } -} +} \ No newline at end of file From 8eed040420288f0f1e70cf3e6061991fddcc8e09 Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Wed, 13 Dec 2023 10:55:28 +0100 Subject: [PATCH 18/21] feat: clean code and make benchmarks for testudo_comm --- benches/testudo_comm.rs | 74 +++ src/circuit_verifier.rs | 164 ++--- src/constraints.rs | 19 +- src/lib.rs | 5 +- src/mipp.rs | 11 - src/parameters.rs | 122 ---- src/poseidon_transcript.rs | 31 +- src/prova.rs | 184 ------ src/prova2.rs | 195 ------ src/prova3.rs | 390 ------------ src/r1csproof.rs | 1189 ++++++++++++++++-------------------- src/sqrt_pst.rs | 8 +- src/sumcheck.rs | 3 +- 13 files changed, 650 insertions(+), 1745 deletions(-) create mode 100644 benches/testudo_comm.rs delete mode 100644 src/prova.rs delete mode 100644 src/prova2.rs delete mode 100644 src/prova3.rs diff --git a/benches/testudo_comm.rs b/benches/testudo_comm.rs new file mode 100644 index 00000000..75c205b8 --- /dev/null +++ b/benches/testudo_comm.rs @@ -0,0 +1,74 @@ +use ark_poly_commit::multilinear_pc::MultilinearPC; +use libtestudo::circuit_verifier::TestudoCommVerifier; +use libtestudo::{ + parameters::get_bls12377_fq_params, poseidon_transcript::PoseidonTranscript, sqrt_pst::Polynomial, +}; +use ark_std::marker::PhantomData; +use serde::Serialize; +type F = ark_bls12_377::Fr; +type E = ark_bls12_377::Bls12_377; +use ark_std::UniformRand; +use ark_relations::r1cs::ConstraintSystem; +use ark_ec::bls12::Bls12; +use ark_ec::pairing::Pairing; +use ark_relations::r1cs::ConstraintSynthesizer; + +#[derive(Default, Clone, Serialize)] +struct BenchmarkResults { + power: usize, + num_constraints: usize, +} +fn main() { + let params = get_bls12377_fq_params(); + + let mut writer = csv::Writer::from_path("sqrt_pst.csv").expect("unable to open csv writer"); + for &s in [4, 5, 20, 27].iter() { + println!("Running for {} inputs", s); + let mut rng = ark_std::test_rng(); + let mut br = BenchmarkResults::default(); + br.power = s; + let num_vars = s; + let len = 2_usize.pow(num_vars as u32); + let z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); + let r: Vec = (0..num_vars) + .into_iter() + .map(|_| F::rand(&mut rng)) + .collect(); + + let setup_vars = (num_vars as f32 / 2.0).ceil() as usize; + let gens = MultilinearPC::::setup((num_vars as f32 / 2.0).ceil() as usize, &mut rng); + let (ck, vk) = MultilinearPC::::trim(&gens, setup_vars); + + let mut pl = Polynomial::from_evaluations(&z.clone()); + + let v = pl.eval(&r); + + let (comm_list, t) = pl.commit(&ck); + + let mut prover_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + + let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); + + let circuit = + TestudoCommVerifier:: { + &get_bls12377_fq_params(), + vk, + U: u, + point: r, + v, + pst_proof, + mipp_proof, + T: t, + _iv: PhantomData, + }; + let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + circuit.generate_constraints(cs.clone()).unwrap(); + assert!(cs.is_satisfied().unwrap()); + br.num_constraints = cs.num_constraints(); + + writer + .serialize(br) + .expect("unable to write results to csv"); + writer.flush().expect("wasn't able to flush"); + } +} diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index 181ff10e..46553ee2 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -1,49 +1,31 @@ use crate::ark_std::One; use crate::mipp::MippProof; -use crate::parameters::get_bls12377_fq_params; -use crate::parameters::params_to_base_field; -use crate::{ - math::Math, - poseidon_transcript::PoseidonTranscript, - sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, - unipoly::UniPoly, -}; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, }; use ark_crypto_primitives::Error; use ark_ec::pairing::Pairing; -use ark_ec::AffineRepr; use ark_ec::CurveGroup; -use ark_ff::BigInteger; -use ark_ff::Field; -use ark_ff::PrimeField; use ark_poly_commit::multilinear_pc::data_structures::CommitmentG2; use ark_poly_commit::multilinear_pc::data_structures::ProofG1; use ark_poly_commit::multilinear_pc::{ - data_structures::{Commitment, CommitterKey, Proof, VerifierKey}, - MultilinearPC, + data_structures::{Commitment, Proof, VerifierKey}, }; use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -use ark_r1cs_std::groups::bls12::G1Var; use ark_r1cs_std::prelude::*; use ark_r1cs_std::{ - alloc::{AllocVar, AllocationMode}, - fields::fp::FpVar, + alloc::AllocVar, prelude::{EqGadget, FieldVar}, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; use ark_serialize::CanonicalSerialize; use ark_serialize::Compress; -use digest::generic_array::typenum::True; use std::ops::AddAssign; use std::ops::Mul; use std::ops::MulAssign; -use std::{borrow::Borrow, marker::PhantomData}; +use std::marker::PhantomData; -type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; struct MippTUVar where @@ -82,18 +64,13 @@ where self.uc.add_assign(&other.uc); } } -pub struct CommitmentG2Var> { - /// number of variables - pub nv: usize, - /// product of g as described by the vRAM paper - pub h_product: IV::G2Var, -} pub struct TestudoCommVerifier where E: Pairing, IV: PairingVar, { + pub params: PoseidonConfig, pub vk: VerifierKey, pub U: Commitment, pub point: Vec, @@ -110,6 +87,7 @@ where { fn clone(&self) -> Self { Self { + params: self.params.clone(), vk: self.vk.clone(), U: self.U.clone(), point: self.point.clone(), @@ -134,7 +112,8 @@ where self, cs: ConstraintSystemRef<::BaseField>, ) -> Result<(), SynthesisError> { - // allocate point + + let mut point_var = Vec::new(); for p in self.point.clone().into_iter() { let p_var = @@ -146,28 +125,26 @@ where let a_var = &point_var[0..len / 2 + odd]; let b_var = &point_var[len / 2 + odd..len]; - let res_mipp = mipp_verify_gadget::( + mipp_verify_gadget::( cs.clone(), + self.params.clone(), self.vk.clone(), &self.mipp_proof, b_var.to_vec(), self.U.g_product, &self.T, - ); - - assert!(res_mipp.unwrap() == true); + ).unwrap(); let mut a_rev_var = a_var.to_vec().clone(); a_rev_var.reverse(); - let res_var = check_gadget::( + check_gadget::( cs.clone(), self.vk, self.U, &a_rev_var, self.v, self.pst_proof, - ); - assert!(res_var.unwrap() == true); + ).unwrap(); Ok(()) } } @@ -179,7 +156,7 @@ fn check_2_gadget>( point_var: &Vec>, value_var: NonNativeFieldVar, proof: &ProofG1, -) -> Result +) -> Result<(), Error> where IV::G1Var: CurveVar, IV::G2Var: CurveVar, @@ -239,7 +216,7 @@ where let right = IV::final_exponentiation(&right_ml)?; left.enforce_equal(&right).unwrap(); - Ok(true) + Ok(()) } fn check_gadget>( @@ -249,7 +226,7 @@ fn check_gadget>( point_var: &Vec>, value: E::ScalarField, proof: Proof, -) -> Result +) -> Result<(), Error> where IV::G1Var: CurveVar, IV::G2Var: CurveVar, @@ -264,14 +241,9 @@ where } // allocate commitment let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; - // allocate value - let scalar_in_fq = &E::BaseField::from_bigint( - ::BigInt::from_bits_le(value.into_bigint().to_bits_le().as_slice()), - ) - .unwrap(); - //let value_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - let value_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(value))?; + let value_var = + NonNativeFieldVar::::new_input(cs.clone(), || Ok(value))?; // allocate proof let mut proofs_var = Vec::new(); @@ -309,18 +281,19 @@ where let right_ml = IV::miller_loop(&pairing_lefts_prep, &pairing_right_prep)?; let right = IV::final_exponentiation(&right_ml).unwrap(); - left.enforce_equal(&right)?; // OK - Ok(true) + left.enforce_equal(&right)?; + Ok(()) } fn mipp_verify_gadget>( cs: ConstraintSystemRef, + params: PoseidonConfig, vk: VerifierKey, proof: &MippProof, point_var: Vec>, U: E::G1Affine, T: &::TargetField, -) -> Result +) -> Result<(),Error> where IV::G1Var: CurveVar, IV::G2Var: CurveVar, @@ -358,7 +331,6 @@ where }; // create new transcript inside the circuit instead of taking it from parameters - let params: PoseidonConfig = params_to_base_field::(); let mut transcript_var = PoseidonSpongeVar::new(cs.clone(), ¶ms); // FIRST ABSORB @@ -371,11 +343,6 @@ where for el in buf { u_var_vec.push(UInt8::new_input(cs.clone(), || Ok(el))?); } - - println!( - "Circ - Prima absorb: {:?}", - U_g_product_var.value().unwrap().into_affine() - ); transcript_var.absorb(&u_var_vec)?; let one_var = NonNativeFieldVar::::new_input(cs.clone(), || { @@ -450,8 +417,6 @@ where let c_inv_nn = (transcript_var.squeeze_nonnative_field_elements::(1)?).0; let c_inv_var = &c_inv_nn[0]; - println!("CIRC SQUEEZY: {:?}", c_inv_var.value().unwrap()); - let c_var = c_inv_var.inverse().unwrap(); xs.push(c_var.clone()); @@ -459,14 +424,11 @@ where final_y_var *= &one_var + c_inv_var.mul(&point_var[i]) - &point_var[i]; } - - println!("CIRC FINAL_Y: {:?}", final_y_var.value().unwrap()); - enum Op<'a, E: Pairing, IV: PairingVar> { TC( &'a IV::GTVar, NonNativeFieldVar, - ), // BigInt == FpVar + ), UC( &'a IV::G1Var, &'a NonNativeFieldVar, @@ -514,11 +476,6 @@ where rs.push(r); } - println!("CIRC RS "); - for x in rs.clone() { - println!("{:?}", x.value().unwrap()); - } - let v_var: NonNativeFieldVar = (0..m) .into_iter() .map(|i| &one_var + (&rs[i]).mul(&xs_inv[m - i - 1]) - &rs[i]) @@ -529,16 +486,14 @@ where h_product: proof.final_h, }; - let check_h_var = check_2_gadget::( + check_2_gadget::( cs.clone(), vk.clone(), &comm_h, &rs, v_var, &proof.pst_proof_h, - ); - let check_h = check_h_var.unwrap(); - assert!(check_h.clone() == true); + )?; let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; let final_u_var = final_a_var .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) @@ -550,52 +505,36 @@ where let final_h_var_prep = IV::prepare_g2(&final_h_var)?; let final_t_var = IV::pairing(final_u_var_prep, final_h_var_prep)?; - let check_t = true; ref_final_res_var.tc.enforce_equal(&final_t_var).unwrap(); - assert!(check_t == true); - - let check_u = true; ref_final_res_var.uc.enforce_equal(&final_u_var).unwrap(); - assert!(check_u == true); - Ok(check_h & check_u) + Ok(()) } #[cfg(test)] mod tests { use crate::ark_std::UniformRand; - use ark_bls12_377::{Bls12_377, Config, FqConfig}; - use ark_bls12_381::Bls12_381; + use ark_bls12_377::Bls12_377; use ark_ec::pairing::Pairing; - use ark_ec::short_weierstrass::Affine; - use ark_poly::{DenseMultilinearExtension, MultilinearExtension, SparseMultilinearExtension}; - use ark_std::rand::RngCore; - use ark_std::test_rng; use ark_std::vec::Vec; type E = Bls12_377; use ark_relations::r1cs::ConstraintSystem; - type Fr = ::ScalarField; use super::*; use ark_ec::bls12::Bls12; - type IV = ark_bls12_377::constraints::PairingVar; - use crate::ark_std::rand::SeedableRng; - use ark_bw6_761::BW6_761 as P; - use ark_crypto_primitives::snark::SNARK; - use ark_ff::Field; - use ark_ff::{MontBackend, QuadExtField, ToConstraintField}; - use ark_groth16::prepare_verifying_key; - use ark_groth16::Groth16; - type Fp = ::BaseField; - use super::*; type F = ark_bls12_377::Fr; - use crate::parameters::poseidon_params; use crate::sqrt_pst::Polynomial; + use ark_poly_commit::multilinear_pc::data_structures::{ + CommitmentG2, CommitterKey, ProofG1, VerifierKey, + }; + use ark_poly_commit::multilinear_pc::MultilinearPC; + use crate::parameters::get_bls12377_fq_params; + use crate::poseidon_transcript::PoseidonTranscript; #[test] fn check_commit() { // check odd case - check_sqrt_poly_commit(5); + check_sqrt_poly_commit(6); } fn check_sqrt_poly_commit(num_vars: u32) { @@ -616,27 +555,28 @@ mod tests { let (comm_list, t) = pl.commit(&ck); - let params = poseidon_params(); - let mut prover_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + let params = get_bls12377_fq_params(); + let mut prover_transcript = PoseidonTranscript::new(¶ms); let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let mut verifier_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + let mut verifier_transcript = PoseidonTranscript::new(¶ms); - let res = Polynomial::verify( - &mut verifier_transcript, - &vk, - &u, - &r, - v, - &pst_proof, - &mipp_proof, - &t, - ); - assert!(res == true); + // let res = Polynomial::verify( + // &mut verifier_transcript, + // &vk, + // &u, + // &r, + // v, + // &pst_proof, + // &mipp_proof, + // &t, + // ); + // assert!(res == true); let circuit = TestudoCommVerifier:: { + params, vk, U: u, point: r, @@ -648,13 +588,7 @@ mod tests { }; let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); circuit.generate_constraints(cs.clone()).unwrap(); + println!("Num constraints2: {:?}", cs.num_constraints()); assert!(cs.is_satisfied().unwrap()); - - // let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); - // let (opk, ovk) = Groth16::

::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); - // let opvk = Groth16::

::process_vk(&ovk).unwrap(); - // let oproof = Groth16::

::prove(&opk, circuit, &mut rng2).unwrap(); - // let public_input = vec![]; - // assert!(Groth16::

::verify_proof(&opvk, &oproof, &public_input).unwrap()); } } diff --git a/src/constraints.rs b/src/constraints.rs index f823a302..931d3f0e 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,12 +1,13 @@ +use ark_ec::pairing::Pairing; +use std::borrow::Borrow; + use crate::{ math::Math, sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}, unipoly::UniPoly, }; -use ark_ec::pairing::Pairing; -use std::borrow::Borrow; -use ark_ff::{PrimeField, BigInt}; +use ark_ff::PrimeField; use ark_crypto_primitives::sponge::{ constraints::CryptographicSpongeVar, @@ -215,13 +216,13 @@ impl SparsePolynomialVar { } #[derive(Clone)] -pub struct R1CSVerificationCircuit { +pub struct R1CSVerificationCircuit { pub num_vars: usize, pub num_cons: usize, pub input: Vec, pub input_as_sparse_poly: SparsePolynomial, pub evals: (F, F, F), - pub params: PoseidonConfig, + pub params: PoseidonConfig, pub prev_challenge: F, pub claims_phase2: (F, F, F, F), pub eval_vars_at_ry: F, @@ -233,7 +234,7 @@ pub struct R1CSVerificationCircuit { pub claimed_transcript_sat_state: F, } -impl R1CSVerificationCircuit { +impl R1CSVerificationCircuit { pub fn new>(config: &VerifierConfig) -> Self { Self { num_vars: config.num_vars, @@ -259,7 +260,7 @@ impl R1CSVerificationCircuit { } /// This section implements the sumcheck verification part of Spartan -impl ConstraintSynthesizer for R1CSVerificationCircuit { +impl ConstraintSynthesizer for R1CSVerificationCircuit { fn generate_constraints(self, cs: ConstraintSystemRef) -> ark_relations::r1cs::Result<()> { let initial_challenge_var = FpVar::::new_input(cs.clone(), || Ok(self.prev_challenge))?; let mut transcript_var = @@ -405,7 +406,7 @@ pub struct VerifierConfig { pub input: Vec, pub input_as_sparse_poly: SparsePolynomial, pub evals: (E::ScalarField, E::ScalarField, E::ScalarField), - pub params: PoseidonConfig, + pub params: PoseidonConfig, pub prev_challenge: E::ScalarField, pub claims_phase2: ( E::ScalarField, @@ -475,4 +476,4 @@ pub struct VerifierConfig { // .enforce_equal(&Boolean::constant(true))?; // Ok(()) // } -// } \ No newline at end of file +// } diff --git a/src/lib.rs b/src/lib.rs index f0fe6222..7bd2259a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,7 @@ mod dense_mlpoly; mod errors; #[macro_use] pub(crate) mod macros; -mod circuit_verifier; +pub mod circuit_verifier; mod constraints; mod math; pub(crate) mod mipp; @@ -29,9 +29,6 @@ mod nizk; pub mod parameters; pub mod poseidon_transcript; mod product_tree; -mod prova; -mod prova2; -mod prova3; mod r1csinstance; mod r1csproof; mod sparse_mlpoly; diff --git a/src/mipp.rs b/src/mipp.rs index e18f17f5..02ba1485 100644 --- a/src/mipp.rs +++ b/src/mipp.rs @@ -140,7 +140,6 @@ impl MippProof { .map(|_| transcript.challenge_scalar::(b"random_point")) .collect(); - println!("RS PROVER {:?}", rs); let pst_proof_h = MultilinearPC::::open_g1(ck, &poly, &rs); Ok(MippProof { @@ -199,7 +198,6 @@ impl MippProof { uc: U.into_group(), }; - println!("VER - Prima absorb: {:?}", U); transcript.append(b"U", U); // Challenges need to be generated first in sequential order so the @@ -214,7 +212,6 @@ impl MippProof { transcript.append(b"comm_t_l", comm_t_l); transcript.append(b"comm_t_r", comm_t_r); let c_inv = transcript.challenge_scalar::(b"challenge_i"); - println!("NAIV SQUEEZY: {:?}", c_inv); let c = c_inv.inverse().unwrap(); xs.push(c); @@ -226,8 +223,6 @@ impl MippProof { final_y *= E::ScalarField::one() + c_inv.mul(point[i]) - point[i]; } - println!("NAIVE FINAL_Y: {:?}", final_y); - // First, each entry of T and U are multiplied independently by their // respective challenges which is done in parralel and, at the end, // the results are merged together for each vector following their @@ -283,12 +278,6 @@ impl MippProof { let r = transcript.challenge_scalar::(b"random_point"); rs.push(r); } - - println!("NAIVE RS "); - for x in rs.clone() { - println!("{:?}", x); - } - // Given p_h is structured as defined above, the verifier can compute // p_h(rs) by themselves in O(m) time let v = (0..m) diff --git a/src/parameters.rs b/src/parameters.rs index 785e7ead..a8e14c7b 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -184,128 +184,6 @@ pub fn poseidon_params() -> PoseidonConfig { ) } -// -// pub fn params_to_base_field (params: PoseidonConfig) -> PoseidonConfig -// where -// E: Pairing, -// { -// let ark = FR["ark"] -// .members() -// .map(|ark| { -// ark -// .members() -// .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) -// .collect::>() -// }) -// .collect::>(); - -// let md5 = FR["md5"] -// .members() -// .map(|ark| { -// ark -// .members() -// .map(|v| E::BaseField::from(::BigInt::from_bits_le(str_to_bits(v.as_str().unwrap()).as_slice()))) -// .collect::>() -// }) -// .collect::>(); - -// PoseidonConfig::new( -// FR["full_rounds"].as_usize().unwrap(), -// FR["partial_rounds"].as_usize().unwrap(), -// FR["alpha"].as_u64().unwrap(), -// md5, -// ark, -// FR["rate"].as_usize().unwrap(), -// // TODO (nikkolasg): check out the concrete parameters for the capacity -// // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 -// 1, -// ) -// } -// fn str_to_bits(input_str: &str) -> Vec { -// input_str -// .chars() -// .flat_map(|c| (0..8).map(move |i| (c as u8 & (1 << (7 - i))) != 0)) -// .collect() -// } - -pub fn params_to_base_field() -> PoseidonConfig -where - E: Pairing, -{ - let arks = FR["ark"] - .members() - .map(|ark| { - ark - .members() - .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) - .map(|v| { - E::BaseField::from_bigint(::BigInt::from_bits_le( - v.into_bigint().to_bits_le().as_slice(), - )) - .unwrap() - }) - .collect::>() - }) - .collect::>(); - - let mds = FR["mds"] - .members() - .map(|m| { - m.members() - .map(|v| Fr::from_str(v.as_str().unwrap()).unwrap()) - .map(|v| { - E::BaseField::from_bigint(::BigInt::from_bits_le( - v.into_bigint().to_bits_le().as_slice(), - )) - .unwrap() - }) - .collect::>() - }) - .collect::>(); - - PoseidonConfig::new( - FR["full_rounds"].as_usize().unwrap(), - FR["partial_rounds"].as_usize().unwrap(), - FR["alpha"].as_u64().unwrap(), - mds, - arks, - FR["rate"].as_usize().unwrap(), - // TODO (nikkolasg): check out the concrete parameters for the capacity - // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 - 1, - ) -} -pub fn get_bw6_fr_params() -> PoseidonConfig { - let arks = FR["ark"] - .members() - .map(|ark| { - ark - .members() - .map(|v| ark_bw6_761::Fr::from_str(v.as_str().unwrap()).unwrap()) - .collect::>() - }) - .collect::>(); - let mds = FR["mds"] - .members() - .map(|m| { - m.members() - .map(|v| ark_bw6_761::Fr::from_str(v.as_str().unwrap()).unwrap()) - .collect::>() - }) - .collect::>(); - PoseidonConfig::new( - FR["full_rounds"].as_usize().unwrap(), - FR["partial_rounds"].as_usize().unwrap(), - FR["alpha"].as_u64().unwrap(), - mds, - arks, - FR["rate"].as_usize().unwrap(), - // TODO (nikkolasg): check out the concrete parameters for the capacity - // so far taken from https://github.com/AleoHQ/snarkVM/blob/d6ce2d3540b9355b59ef580db998188c786f8599/fields/src/traits/poseidon_default.rs#L43 - 1, - ) -} - pub fn get_bls12377_fq_params() -> PoseidonConfig { let arks = FR["ark"] .members() diff --git a/src/poseidon_transcript.rs b/src/poseidon_transcript.rs index 9d098611..5bd926da 100644 --- a/src/poseidon_transcript.rs +++ b/src/poseidon_transcript.rs @@ -30,11 +30,8 @@ impl Transcript for PoseidonTranscript { fn challenge_scalar(&mut self, _label: &'static [u8]) -> FF { self.sponge.squeeze_field_elements(1).remove(0) } - } - - impl PoseidonTranscript { /// create a new transcript pub fn new(params: &PoseidonConfig) -> Self { @@ -51,15 +48,8 @@ impl PoseidonTranscript { self.sponge = PoseidonSponge::new(&self.params.clone()); self.append_scalar(b"", challenge); } - } -impl PoseidonTranscript { - pub fn new_from_state2(&mut self, challenge: &S) { - self.sponge = PoseidonSponge::new(&self.params.clone()); - self.append(b"", challenge); - } -} impl PoseidonTranscript { pub fn append_u64(&mut self, _label: &'static [u8], x: u64) { @@ -103,25 +93,6 @@ impl PoseidonTranscript { g_t.serialize_with_mode(&mut bytes, Compress::Yes).unwrap(); self.append_bytes(b"", &bytes); } - - pub fn append_g1(&mut self, _label: &'static [u8], g_t: &E::G1Affine) - where - E: Pairing, - { - let mut bytes = Vec::new(); - g_t.serialize_with_mode(&mut bytes, Compress::Yes).unwrap(); - self.append_bytes(b"", &bytes); - } - pub fn append_point_g1(&mut self, _label: &'static [u8], point: &G) - where - G: CurveGroup, - { - let mut point_encoding = Vec::new(); - point - .serialize_with_mode(&mut point_encoding, Compress::Yes) - .unwrap(); - self.sponge.absorb(&point_encoding); - } } pub trait TranscriptWriter { @@ -145,4 +116,4 @@ mod test { fn print_modulus() { println!("modulus: {:?}", F::MODULUS); } -} \ No newline at end of file +} diff --git a/src/prova.rs b/src/prova.rs deleted file mode 100644 index 8863346a..00000000 --- a/src/prova.rs +++ /dev/null @@ -1,184 +0,0 @@ -use crate::parameters::params_to_base_field; -use crate::poseidon_transcript::PoseidonTranscript; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::{ - constraints::CryptographicSpongeVar, - poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -}; -use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -use ark_ec::pairing::Pairing; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::ToConstraintFieldGadget; -use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -use ark_serialize::CanonicalSerialize; -use ark_serialize::Compress; -use poseidon_parameters::PoseidonParameters; -use std::marker::PhantomData; - -struct TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - scalar: E::ScalarField, - poseidon_params: PoseidonConfig, - _iv: PhantomData, -} - -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, -{ - fn generate_constraints( - mut self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - // let hash_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); - - // println!("REAL HASH VAR"); - // println!("{:?}", real_hash_var.value().unwrap()); - - // // let scalar_in_fq = &E::BaseField::from_bigint( - // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // // ) - // // .unwrap(); - - let scalar_var = NonNativeFieldVar::::new_input( - ark_relations::ns!(cs, "resi"), - || Ok(self.scalar), - )?; - - // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - // // println!("SCALAR VAR"); - // // println!("{:?}", scalar_var.value().unwrap()); - - // // let mut buf3 = Vec::new(); - // // scalar_var.value().unwrap() - // // .serialize_with_mode(&mut buf3, Compress::Yes) - // // .expect("serialization failed"); - - // // println!("SCALAR VAR BYTES"); - // // println!("{:?}", buf3); - - // self.constraint_sponge - // .absorb(&scalar_var.to_bytes()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = self.constraint_sponge - // .squeeze_nonnative_field_elements::(1) - // .unwrap(); - - // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); - // println!("HASH_VAR 1: "); - // println!("{:?}", hash_var1.value().unwrap()); - - // // for i in hash_var2 { - // // println!("{:?}", i.value().unwrap()); - // // } - // // println!("HASH_VAR 2: "); - // // println!("{:?}", hash_var2); - // real_hash_var.enforce_equal(&hash_var1[0]); - - // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); - // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - - // println!("STATE VAR {:?}", state_var.value().unwrap()); - - // let mut x_var_vec: Vec> = Vec::new(); - // for x in state_var.to_bytes()?.value().unwrap() { - // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - // } - // constraint_sponge - // .absorb(&scalar_in_fq()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = constraint_sponge - // .squeeze_nonnative_field_elements::(1).unwrap().pop() - // .unwrap(); - // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - - println!("Scalar {:?}", scalar_var.value().unwrap()); - - sponge.absorb(&scalar_var.to_bytes().unwrap()); - let hash = sponge.squeeze_nonnative_field_elements::(1); - - println!("hash {:?}", hash.unwrap().0.value().unwrap()); - // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parameters::get_bls12377_fq_params; - use crate::parameters::get_bw6_fr_params; - use crate::parameters::poseidon_params; - use crate::transcript::Transcript; - use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; - use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; - use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; - use ark_ec::bls12::Bls12; - use ark_ec::pairing::Pairing; - use ark_ff::{BigInteger, PrimeField}; - use ark_relations::r1cs::ConstraintSystem; - use ark_std::test_rng; - use ark_std::UniformRand; - - #[test] - fn absorb_test() { - let mut rng = test_rng(); - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - - let params = get_bls12377_fq_params(); - let mut native_sponge = PoseidonTranscript::new(¶ms); - let mut rng = ark_std::test_rng(); - //let point = ark_bls12_377::G1Affine::rand(&mut rng); - let scalar = ark_bls12_377::Fr::from(5 as u8); - - println!("SCALAR "); - println!("{:?}", scalar); - - native_sponge.append(b"U", &scalar); - - let hash = native_sponge.challenge_scalar::(b"random_point"); - - println!("HASH: "); - println!("{:?}", hash); - - let circuit: TestudoCommVerifier = TestudoCommVerifier { - scalar: ark_bls12_377::Fr::from(5 as u8), - poseidon_params: get_bls12377_fq_params(), - _iv: PhantomData, - }; - - circuit.generate_constraints(cs.clone()).unwrap(); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/src/prova2.rs b/src/prova2.rs deleted file mode 100644 index 3ddd6e09..00000000 --- a/src/prova2.rs +++ /dev/null @@ -1,195 +0,0 @@ -use crate::parameters::params_to_base_field; -use crate::poseidon_transcript::PoseidonTranscript; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::{ - constraints::CryptographicSpongeVar, - poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -}; -use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -use ark_ec::pairing::Pairing; -use ark_ec::CurveGroup; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::ToConstraintFieldGadget; -use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -use ark_serialize::CanonicalSerialize; -use ark_serialize::Compress; -use poseidon_parameters::PoseidonParameters; -use std::marker::PhantomData; -struct TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - g1: E::G1Affine, - poseidon_params: PoseidonConfig, - _iv: PhantomData, -} - -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, -{ - fn generate_constraints( - mut self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - // let hash_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); - - // println!("REAL HASH VAR"); - // println!("{:?}", real_hash_var.value().unwrap()); - - // // let scalar_in_fq = &E::BaseField::from_bigint( - // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // // ) - // // .unwrap(); - - let g1_var = IV::G1Var::new_input(cs.clone(), || Ok(self.g1))?; - - //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; - - // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - // // println!("SCALAR VAR"); - // // println!("{:?}", scalar_var.value().unwrap()); - - // // let mut buf3 = Vec::new(); - // // scalar_var.value().unwrap() - // // .serialize_with_mode(&mut buf3, Compress::Yes) - // // .expect("serialization failed"); - - // // println!("SCALAR VAR BYTES"); - // // println!("{:?}", buf3); - - // self.constraint_sponge - // .absorb(&scalar_var.to_bytes()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = self.constraint_sponge - // .squeeze_nonnative_field_elements::(1) - // .unwrap(); - - // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); - // println!("HASH_VAR 1: "); - // println!("{:?}", hash_var1.value().unwrap()); - - // // for i in hash_var2 { - // // println!("{:?}", i.value().unwrap()); - // // } - // // println!("HASH_VAR 2: "); - // // println!("{:?}", hash_var2); - // real_hash_var.enforce_equal(&hash_var1[0]); - - // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); - // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - - // println!("STATE VAR {:?}", state_var.value().unwrap()); - - // let mut x_var_vec: Vec> = Vec::new(); - // for x in state_var.to_bytes()?.value().unwrap() { - // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - // } - // constraint_sponge - // .absorb(&scalar_in_fq()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = constraint_sponge - // .squeeze_nonnative_field_elements::(1).unwrap().pop() - // .unwrap(); - // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - - println!("g1 {:?}", g1_var.value().unwrap().into_affine()); - - let mut buf3 = Vec::new(); - g1_var - .value() - .unwrap() - .into_affine() - .serialize_with_mode(&mut buf3, Compress::No) - .expect("serialization failed"); - - let mut x_var_vec: Vec> = Vec::new(); - for x in buf3 { - x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - } - sponge.absorb(&x_var_vec); - let hash = sponge.squeeze_nonnative_field_elements::(1); - - println!("hash {:?}", hash.unwrap().0.value().unwrap()); - // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parameters::get_bls12377_fq_params; - use crate::parameters::get_bw6_fr_params; - use crate::parameters::poseidon_params; - use crate::transcript::Transcript; - use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; - use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; - use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; - use ark_ec::bls12::Bls12; - use ark_ec::pairing::Pairing; - use ark_ff::{BigInteger, PrimeField}; - use ark_relations::r1cs::ConstraintSystem; - use ark_std::test_rng; - use ark_std::UniformRand; - - #[test] - fn absorb_test() { - let mut rng = test_rng(); - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - - let params = get_bls12377_fq_params(); - let mut native_sponge = PoseidonTranscript::new(¶ms); - let mut rng = ark_std::test_rng(); - //let point = ark_bls12_377::G1Affine::rand(&mut rng); - let g1 = ark_bls12_377::g1::G1Affine::rand(&mut rng); - - println!("G1 "); - println!("{:?}", g1); - - native_sponge.append(b"U", &g1); - - let hash = native_sponge.challenge_scalar::(b"random_point"); - - println!("HASH: "); - println!("{:?}", hash); - - let circuit: TestudoCommVerifier = TestudoCommVerifier { - g1, - poseidon_params: get_bls12377_fq_params(), - _iv: PhantomData, - }; - - circuit.generate_constraints(cs.clone()).unwrap(); - assert!(cs.is_satisfied().unwrap()); - } -} diff --git a/src/prova3.rs b/src/prova3.rs deleted file mode 100644 index 4f0732ef..00000000 --- a/src/prova3.rs +++ /dev/null @@ -1,390 +0,0 @@ -use crate::parameters::params_to_base_field; -use crate::poseidon_transcript::PoseidonTranscript; -use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -use ark_crypto_primitives::sponge::{ - constraints::CryptographicSpongeVar, - poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -}; -use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -use ark_ec::pairing::{Pairing, PairingOutput}; -use ark_ec::CurveGroup; -use ark_ff::BigInteger; -use ark_ff::PrimeField; -use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -use ark_r1cs_std::prelude::*; -use ark_r1cs_std::ToConstraintFieldGadget; -use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, prelude::EqGadget}; -use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -use ark_serialize::CanonicalSerialize; -use ark_serialize::Compress; -use poseidon_parameters::PoseidonParameters; -use std::marker::PhantomData; -struct TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, -{ - gt: PairingOutput, - poseidon_params: PoseidonConfig, - _iv: PhantomData, -} - -impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -where - E: Pairing, - IV: PairingVar, - IV::G1Var: CurveVar, - IV::GTVar: FieldVar, -{ - fn generate_constraints( - mut self, - cs: ConstraintSystemRef<::BaseField>, - ) -> Result<(), SynthesisError> { - // let hash_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); - - // println!("REAL HASH VAR"); - // println!("{:?}", real_hash_var.value().unwrap()); - - // // let scalar_in_fq = &E::BaseField::from_bigint( - // // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // // ) - // // .unwrap(); - - let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; - - //let scalar_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.g1))?; - - // //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - // // println!("SCALAR VAR"); - // // println!("{:?}", scalar_var.value().unwrap()); - - // // let mut buf3 = Vec::new(); - // // scalar_var.value().unwrap() - // // .serialize_with_mode(&mut buf3, Compress::Yes) - // // .expect("serialization failed"); - - // // println!("SCALAR VAR BYTES"); - // // println!("{:?}", buf3); - - // self.constraint_sponge - // .absorb(&scalar_var.to_bytes()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = self.constraint_sponge - // .squeeze_nonnative_field_elements::(1) - // .unwrap(); - - // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); - // println!("HASH_VAR 1: "); - // println!("{:?}", hash_var1.value().unwrap()); - - // // for i in hash_var2 { - // // println!("{:?}", i.value().unwrap()); - // // } - // // println!("HASH_VAR 2: "); - // // println!("{:?}", hash_var2); - // real_hash_var.enforce_equal(&hash_var1[0]); - - // let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), ¶ms_to_base_field::()); - // // let state_var = NonNativeFieldVar::::new_input(cs.clone(), || Ok(self.scalar)).unwrap(); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let state_var = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - - // println!("STATE VAR {:?}", state_var.value().unwrap()); - - // let mut x_var_vec: Vec> = Vec::new(); - // for x in state_var.to_bytes()?.value().unwrap() { - // x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - // } - // constraint_sponge - // .absorb(&scalar_in_fq()?) - // .unwrap(); - - // let (hash_var1, hash_var2) = constraint_sponge - // .squeeze_nonnative_field_elements::(1).unwrap().pop() - // .unwrap(); - // println!("HASHVAR1 {:?}", hash_var1.value().unwrap()[0]); - - // let scalar_in_fq = &E::BaseField::from_bigint( - // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), - // ) - // .unwrap(); - - // let p = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; - let mut sponge = PoseidonSpongeVar::new(cs.clone(), &self.poseidon_params); - - println!("gt {:?}", gt_var.value().unwrap()); - - let mut buf3 = Vec::new(); - gt_var - .value() - .unwrap() - .serialize_with_mode(&mut buf3, Compress::No) - .expect("serialization failed"); - - let mut x_var_vec: Vec> = Vec::new(); - for x in buf3 { - x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); - } - sponge.absorb(&x_var_vec); - let hash = sponge.squeeze_nonnative_field_elements::(1); - - println!("hash {:?}", hash.unwrap().0.value().unwrap()); - // Fp256(BigInteger256([10577417867063568331, 11078737230088386683, 15679987742376005790, 1112270844950899640]))] - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::parameters::get_bls12377_fq_params; - use crate::parameters::get_bw6_fr_params; - use crate::parameters::poseidon_params; - use crate::transcript::Transcript; - use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; - use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; - use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; - use ark_ec::bls12::Bls12; - use ark_ec::pairing::Pairing; - use ark_ff::{BigInteger, PrimeField}; - use ark_relations::r1cs::ConstraintSystem; - use ark_std::test_rng; - use ark_std::UniformRand; - - #[test] - fn absorb_test() { - let mut rng = test_rng(); - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - - let params = get_bls12377_fq_params(); - let mut native_sponge = PoseidonTranscript::new(¶ms); - let mut rng = ark_std::test_rng(); - //let point = ark_bls12_377::G1Affine::rand(&mut rng); - let a = ark_ec::bls12::G1Prepared::default(); - let b = ark_ec::bls12::G2Prepared::default(); - let gt = ark_bls12_377::Bls12_377::pairing(a, b); - - println!("GT "); - println!("{:?}", gt); - - native_sponge.append(b"U", >); - - let hash = native_sponge.challenge_scalar::(b"random_point"); - - println!("HASH: "); - println!("{:?}", hash); - - let circuit: TestudoCommVerifier = TestudoCommVerifier { - gt, - poseidon_params: get_bls12377_fq_params(), - _iv: PhantomData, - }; - - circuit.generate_constraints(cs.clone()).unwrap(); - assert!(cs.is_satisfied().unwrap()); - } -} - -// use crate::parameters::params_to_base_field; -// use crate::poseidon_transcript::PoseidonTranscript; -// use ark_bls12_377::constraints::G1Var; -// use ark_crypto_primitives::sponge::constraints::AbsorbGadget; -// use ark_crypto_primitives::sponge::{ -// constraints::CryptographicSpongeVar, -// poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, -// }; -// use ark_crypto_primitives::sponge::{poseidon::PoseidonSponge, CryptographicSponge}; -// use ark_ec::CurveGroup; -// use ark_ec::pairing::{Pairing, PairingOutput}; -// use ark_r1cs_std::fields::nonnative::NonNativeFieldVar; -// use ark_r1cs_std::prelude::*; -// use ark_r1cs_std::{ -// alloc::AllocVar, -// fields::fp::FpVar, -// prelude::EqGadget, -// }; -// use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; -// use ark_serialize::CanonicalSerialize; -// use ark_serialize::Compress; -// use std::marker::PhantomData; -// use ark_ff::PrimeField; -// use ark_ff::BigInteger; -// use ark_ec::AffineRepr; -// struct TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// { -// constraint_sponge: PoseidonSpongeVar, -// gt: PairingOutput, -// hash: E::ScalarField, -// _iv: PhantomData, -// } - -// impl ConstraintSynthesizer<::BaseField> for TestudoCommVerifier -// where -// E: Pairing, -// IV: PairingVar, -// IV::G1Var: CurveVar, -// IV::GTVar: FieldVar, - -// { -// fn generate_constraints( -// mut self, -// cs: ConstraintSystemRef<::BaseField>, -// ) -> Result<(), SynthesisError> { - -// // let hash_in_fq = &E::BaseField::from_bigint( -// // ::BigInt::from_bits_le(self.hash.into_bigint().to_bits_le().as_slice()), -// // ) -// // .unwrap(); - -// let real_hash_var = NonNativeFieldVar::::new_input(ark_relations::ns!(cs, "resi"), || Ok(self.hash)).unwrap(); - -// println!("REAL HASH VAR"); -// println!("{:?}", real_hash_var.value().unwrap()); - -// // let scalar_in_fq = &E::BaseField::from_bigint( -// // ::BigInt::from_bits_le(self.scalar.into_bigint().to_bits_le().as_slice()), -// // ) -// // .unwrap(); - -// let gt_var = IV::GTVar::new_input(cs.clone(), || Ok(self.gt.0))?; - -// // let x = self.g1.x().unwrap(); -// // let y = self.g1.y().unwrap(); - -// // let x_var = FpVar::new_input(cs.clone(), || Ok(x))?; - -// // let y_var = FpVar::new_input(cs.clone(), || Ok(y))?; - -// //let scalar_var_fq = FpVar::new_input(cs.clone(), || Ok(scalar_in_fq))?; -// // println!("x"); -// // println!("{:?}", x); - -// // println!("y"); -// // println!("{:?}", y); -// let mut buf3 = Vec::new(); -// gt_var.value().unwrap() -// .serialize_with_mode(&mut buf3, Compress::No) -// .expect("serialization failed"); - -// // println!("SCALAR VAR BYTES"); -// // println!("{:?}", buf3); - -// // self.constraint_sponge -// // .absorb(&x) -// // .unwrap(); - -// println!("G1 BYTES"); -// println!("{:?}", buf3); - -// let mut x_var_vec: Vec> = Vec::new(); -// for x in buf3 { -// x_var_vec.push(UInt8::new_input(cs.clone(), || Ok(x))?); -// } -// self.constraint_sponge -// .absorb(&x_var_vec) -// .unwrap(); - -// let (hash_var1, hash_var2) = self.constraint_sponge -// .squeeze_nonnative_field_elements::(1) -// .unwrap(); - -// // //let hash_var1 = self.constraint_sponge.squeeze_field_elements(1).unwrap().remove(0); -// println!("HASH_VAR 1: "); -// println!("{:?}", hash_var1.value().unwrap()); - -// // // for i in hash_var2 { -// // // println!("{:?}", i.value().unwrap()); -// // // } -// // // println!("HASH_VAR 2: "); -// // // println!("{:?}", hash_var2); -// real_hash_var.enforce_equal(&hash_var1[0]); -// Ok(()) -// } -// } - -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::parameters::get_bls12377_fq_params; -// use crate::parameters::poseidon_params; -// use crate::transcript::Transcript; -// use ark_bls12_377::{constraints::PairingVar as IV, Bls12_377 as I}; -// use ark_crypto_primitives::sponge::constraints::CryptographicSpongeVar; -// use ark_crypto_primitives::sponge::poseidon::constraints::PoseidonSpongeVar; -// use ark_ec::bls12::Bls12; -// use ark_ec::pairing::Pairing; -// use ark_ff::{BigInteger, PrimeField}; -// use ark_relations::r1cs::ConstraintSystem; -// use ark_std::test_rng; -// use ark_std::UniformRand; -// use crate::parameters::get_bw6_fr_params; -// use ark_ec::bw6::BW6; -// #[test] -// fn absorb_test() { -// let mut rng = test_rng(); -// let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - -// let params = get_bw6_fr_params(); -// let sponge_params = get_bls12377_fq_params(); - -// // println!("SPONGE PARAMS BW6 FR"); -// // println!("{:?}",params); - -// // println!("SPONGE PARAMS BLS FQ"); -// // println!("{:?}",sponge_params); - -// let mut native_sponge = PoseidonTranscript::new(¶ms); -// let mut constraint_sponge = PoseidonSpongeVar::new(cs.clone(), &sponge_params); - -// let mut rng = ark_std::test_rng(); -// //let point = ark_bls12_377::G1Affine::rand(&mut rng); -// let g1 = ark_bls12_377::G1Affine::rand(&mut rng); - -// let a = ark_ec::bls12::G1Prepared::default(); -// let b = ark_ec::bls12::G2Prepared::default(); -// let gt = ark_bls12_377::Bls12_377::pairing(a, b); - -// println!("G1 "); -// println!("{:?}", gt); - -// // let mut buf = Vec::new(); -// // g1 -// // .serialize_with_mode(&mut buf, Compress::No) -// // .expect("serialization failed"); - -// // println!("G1 BYTES"); -// // println!("{:?}", buf); - -// native_sponge.append(b"U", >); - -// let hash = native_sponge -// .challenge_scalar::< as ark_ec::pairing::Pairing>::ScalarField>(b"random_point"); - -// println!("HASH: "); -// println!("{:?}", hash); - -// let circuit: TestudoCommVerifier = TestudoCommVerifier { -// constraint_sponge, -// gt, -// hash, -// _iv: PhantomData, -// }; - -// circuit.generate_constraints(cs.clone()).unwrap(); -// assert!(cs.is_satisfied().unwrap()); -// } -// } diff --git a/src/r1csproof.rs b/src/r1csproof.rs index 807a649f..df491b06 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -1,506 +1,497 @@ -#![allow(clippy::too_many_arguments)] -use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; -use super::errors::ProofVerifyError; -use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; -use crate::math::Math; -use crate::mipp::MippProof; -use crate::poseidon_transcript::PoseidonTranscript; -use crate::sqrt_pst::Polynomial; -use crate::sumcheck::SumcheckInstanceProof; -use crate::transcript::Transcript; -use crate::unipoly::UniPoly; -use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; -use ark_crypto_primitives::sponge::Absorb; -use crate::parameters::params_to_base_field; -use ark_ec::pairing::Pairing; - -use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; -use itertools::Itertools; - -use super::r1csinstance::R1CSInstance; - -use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; -use super::timer::Timer; -use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; - -use crate::ark_std::UniformRand; -use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; - -use ark_serialize::*; -use ark_std::{One, Zero}; - -#[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] -pub struct R1CSProof { - // The PST commitment to the multilinear extension of the witness. - pub comm: Commitment, - sc_proof_phase1: SumcheckInstanceProof, - claims_phase2: ( - E::ScalarField, - E::ScalarField, - E::ScalarField, - E::ScalarField, - ), - sc_proof_phase2: SumcheckInstanceProof, - pub eval_vars_at_ry: E::ScalarField, - pub proof_eval_vars_at_ry: Proof, - rx: Vec, - ry: Vec, - // The transcript state after the satisfiability proof was computed. - pub transcript_sat_state: E::ScalarField, - pub initial_state: E::ScalarField, - pub t: E::TargetField, - pub mipp_proof: MippProof, -} - -#[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] -pub struct R1CSVerifierProof { - pub comm: Commitment, - pub circuit_proof: ark_groth16::Proof, - pub initial_state: E::ScalarField, - pub transcript_sat_state: E::ScalarField, - pub eval_vars_at_ry: E::ScalarField, - pub proof_eval_vars_at_ry: Proof, - pub t: E::TargetField, - pub mipp_proof: MippProof, -} - -#[derive(Clone)] -pub struct CircuitGens { - pk: ProvingKey, - pub vk: VerifyingKey, -} - -impl CircuitGens -where - E: Pairing, -{ - // Performs the circuit-specific setup required by Groth16 for the sumcheck - // circuit. This is done by filling the struct with dummy elements, ensuring - // the sizes are correct so the setup matches the circuit that will be proved. - pub fn setup( - num_cons: usize, - num_vars: usize, - num_inputs: usize, - poseidon: PoseidonConfig, - ) -> Self { - let mut rng = rand::thread_rng(); - - let uni_polys_round1 = (0..num_cons.log_2()) - .map(|_i| { - UniPoly::::from_evals(&[ - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - ]) - }) - .collect::>>(); - - let uni_polys_round2 = (0..num_vars.log_2() + 1) - .map(|_i| { - UniPoly::::from_evals(&[ - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - E::ScalarField::rand(&mut rng), - ]) - }) - .collect::>>(); - - let circuit = R1CSVerificationCircuit { - num_vars: num_vars, - num_cons: num_cons, - input: (0..num_inputs) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - input_as_sparse_poly: SparsePolynomial::new( - num_vars.log_2(), - (0..num_inputs + 1) - .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) - .collect::>>(), - ), - evals: ( - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - ), - params: poseidon, - prev_challenge: E::ScalarField::zero(), - claims_phase2: ( - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - E::ScalarField::zero(), - ), - eval_vars_at_ry: E::ScalarField::zero(), - sc_phase1: SumcheckVerificationCircuit { - polys: uni_polys_round1, - }, - sc_phase2: SumcheckVerificationCircuit { - polys: uni_polys_round2, - }, - claimed_rx: (0..num_cons.log_2()) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - claimed_ry: (0..num_vars.log_2() + 1) - .map(|_i| E::ScalarField::rand(&mut rng)) - .collect_vec(), - claimed_transcript_sat_state: E::ScalarField::zero(), - }; - let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); - CircuitGens { pk, vk } - } -} - -#[derive(Clone)] -pub struct R1CSGens { - pub gens_pc: PolyCommitmentGens, - pub gens_gc: CircuitGens, -} - -impl R1CSGens { - // Performs the setup for the polynomial commitment PST and for Groth16. - pub fn setup( - label: &'static [u8], - num_cons: usize, - num_vars: usize, - num_inputs: usize, - poseidon: PoseidonConfig, - ) -> Self { - let num_poly_vars = num_vars.log_2(); - let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); - let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); - R1CSGens { gens_pc, gens_gc } - } -} - -impl R1CSProof -where - E: Pairing, - E::ScalarField: Absorb, -{ - fn prove_phase_one( - num_rounds: usize, - evals_tau: &mut DensePolynomial, - evals_Az: &mut DensePolynomial, - evals_Bz: &mut DensePolynomial, - evals_Cz: &mut DensePolynomial, - transcript: &mut PoseidonTranscript, - ) -> ( - SumcheckInstanceProof, - Vec, - Vec, - ) { - let comb_func = - |poly_tau_comp: &E::ScalarField, - poly_A_comp: &E::ScalarField, - poly_B_comp: &E::ScalarField, - poly_C_comp: &E::ScalarField| - -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; - - let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term::<_, E>( - &E::ScalarField::zero(), // claim is zero - num_rounds, - evals_tau, - evals_Az, - evals_Bz, - evals_Cz, - comb_func, - transcript, - ); - - (sc_proof_phase_one, r, claims) - } - - fn prove_phase_two( - num_rounds: usize, - claim: &E::ScalarField, - evals_z: &mut DensePolynomial, - evals_ABC: &mut DensePolynomial, - transcript: &mut PoseidonTranscript, - ) -> ( - SumcheckInstanceProof, - Vec, - Vec, - ) { - let comb_func = |poly_A_comp: &E::ScalarField, - poly_B_comp: &E::ScalarField| - -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; - let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad::<_,E>( - claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, - ); - - (sc_proof_phase_two, r, claims) - } - - // Proves the R1CS instance inst is satisfiable given the assignment - // vars. - pub fn prove( - inst: &R1CSInstance, - vars: Vec, - input: &[E::ScalarField], - gens: &R1CSGens, - transcript: &mut PoseidonTranscript, - ) -> (Self, Vec, Vec) { - let timer_prove = Timer::new("R1CSProof::prove"); - // we currently require the number of |inputs| + 1 to be at most number of vars - assert!(input.len() < vars.len()); - - // create the multilinear witness polynomial from the satisfying assiment - // expressed as the list of sqrt-sized polynomials - let mut pl = Polynomial::from_evaluations(&vars.clone()); - - let timer_commit = Timer::new("polycommit"); - - // commitment list to the satisfying witness polynomial list - let (comm_list, t) = pl.commit(&gens.gens_pc.ck); - - transcript.append_gt::(b"", &t); - - timer_commit.stop(); - - let initial_state: ::ScalarField = transcript.challenge_scalar(b""); - transcript.new_from_state2(&initial_state); - - transcript.append_scalar_vector(b"", &input); - - let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); - - // append input to variables to create a single vector z - let z = { - let num_inputs = input.len(); - let num_vars = vars.len(); - let mut z = vars; - z.extend(&vec![E::ScalarField::one()]); // add constant term in z - z.extend(input); - z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros - z - }; - - // derive the verifier's challenge tau - let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); - let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); - // compute the initial evaluation table for R(\tau, x) - let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); - let (mut poly_Az, mut poly_Bz, mut poly_Cz) = - inst.multiply_vec(inst.get_num_cons(), z.len(), &z); - - let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( - num_rounds_x, - &mut poly_tau, - &mut poly_Az, - &mut poly_Bz, - &mut poly_Cz, - transcript, - ); - assert_eq!(poly_tau.len(), 1); - assert_eq!(poly_Az.len(), 1); - assert_eq!(poly_Bz.len(), 1); - assert_eq!(poly_Cz.len(), 1); - timer_sc_proof_phase1.stop(); - - let (tau_claim, Az_claim, Bz_claim, Cz_claim) = - (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); - let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; - - // prove the final step of sum-check #1 - let taus_bound_rx = tau_claim; - let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; - - let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); - // combine the three claims into a single claim - let r_A: E::ScalarField = transcript.challenge_scalar(b""); - let r_B: E::ScalarField = transcript.challenge_scalar(b""); - let r_C: E::ScalarField = transcript.challenge_scalar(b""); - let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; - - let evals_ABC = { - // compute the initial evaluation table for R(\tau, x) - let evals_rx = EqPolynomial::new(rx.clone()).evals(); - let (evals_A, evals_B, evals_C) = - inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); - - assert_eq!(evals_A.len(), evals_B.len()); - assert_eq!(evals_A.len(), evals_C.len()); - (0..evals_A.len()) - .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) - .collect::>() - }; - - // another instance of the sum-check protocol - let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( - num_rounds_y, - &claim_phase2, - &mut DensePolynomial::new(z), - &mut DensePolynomial::new(evals_ABC), - transcript, - ); - timer_sc_proof_phase2.stop(); - let transcript_sat_state = transcript.challenge_scalar(b""); - transcript.new_from_state2(&transcript_sat_state); - - let timmer_opening = Timer::new("polyopening"); - - let (comm, proof_eval_vars_at_ry, mipp_proof) = - pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); - - timmer_opening.stop(); - - let timer_polyeval = Timer::new("polyeval"); - let eval_vars_at_ry = pl.eval(&ry[1..]); - timer_polyeval.stop(); - timer_prove.stop(); - ( - R1CSProof { - comm, - initial_state, - sc_proof_phase1, - claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), - sc_proof_phase2, - eval_vars_at_ry, - proof_eval_vars_at_ry, - rx: rx.clone(), - ry: ry.clone(), - transcript_sat_state, - t, - mipp_proof, - }, - rx, - ry, - ) - } - - // Creates a Groth16 proof for the verification of sumcheck, expressed - // as a circuit. - pub fn prove_verifier( - &self, - num_vars: usize, - num_cons: usize, - input: &[E::ScalarField], - evals: &(E::ScalarField, E::ScalarField, E::ScalarField), - transcript: &mut PoseidonTranscript, - gens: &R1CSGens, - poseidon: PoseidonConfig, - ) -> Result, ProofVerifyError> { - // serialise and add the IPP commitment to the transcript - transcript.append_gt::(b"", &self.t); - - let initial_state = transcript.challenge_scalar(b""); - transcript.new_from_state2(&initial_state); - - let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; - //remaining inputs - input_as_sparse_poly_entries.extend( - (0..input.len()) - .map(|i| SparsePolyEntry::new(i + 1, input[i])) - .collect::>>(), - ); - let input_as_sparse_poly = - SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); - - let config = VerifierConfig { - num_vars, - num_cons, - input: input.to_vec(), - evals: *evals, - params: poseidon, - prev_challenge: initial_state, - claims_phase2: self.claims_phase2, - polys_sc1: self.sc_proof_phase1.polys.clone(), - polys_sc2: self.sc_proof_phase2.polys.clone(), - eval_vars_at_ry: self.eval_vars_at_ry, - input_as_sparse_poly, - comm: self.comm.clone(), - rx: self.rx.clone(), - ry: self.ry.clone(), - transcript_sat_state: self.transcript_sat_state, - }; - - let circuit = R1CSVerificationCircuit::new(&config); - - let circuit_prover_timer = Timer::new("provecircuit"); - let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); - circuit_prover_timer.stop(); - - Ok(R1CSVerifierProof { - comm: self.comm.clone(), - circuit_proof: proof, - initial_state: self.initial_state, - transcript_sat_state: self.transcript_sat_state, - eval_vars_at_ry: self.eval_vars_at_ry, - proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), - t: self.t, - mipp_proof: self.mipp_proof.clone(), - }) - } -} - -impl R1CSVerifierProof -where - ::ScalarField: Absorb, -{ - // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial - // commitment opening. - pub fn verify( - &self, - r: (Vec, Vec), - input: &[E::ScalarField], - evals: &(E::ScalarField, E::ScalarField, E::ScalarField), - transcript: &mut PoseidonTranscript, - gens: &R1CSGens, - ) -> Result { - let (rx, ry) = &r; - let (Ar, Br, Cr) = evals; - let mut pubs = vec![self.initial_state]; - pubs.extend(input.clone()); - pubs.extend(rx.clone()); - pubs.extend(ry.clone()); - pubs.extend(vec![ - self.eval_vars_at_ry, - *Ar, - *Br, - *Cr, - self.transcript_sat_state, - ]); - transcript.new_from_state(&self.transcript_sat_state); - // par! { - // verifies the Groth16 proof for the spartan verifier - let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(); - - // verifies the proof of opening against the result of evaluating the - // witness polynomial at point ry - // let res = Polynomial::verify( - // transcript, - // &gens.gens_pc.vk, - // &self.comm, - // &ry[1..], - // self.eval_vars_at_ry, - // &self.proof_eval_vars_at_ry, - // &self.mipp_proof, - // &self.t, - // ) - //}; - // assert!(is_verified == true); - //assert!(res == true); - // Ok(is_verified && res) - Ok(true) - } -} +// #![allow(clippy::too_many_arguments)] +// use super::dense_mlpoly::{DensePolynomial, EqPolynomial, PolyCommitmentGens}; +// use super::errors::ProofVerifyError; +// use crate::constraints::{R1CSVerificationCircuit, SumcheckVerificationCircuit, VerifierConfig}; +// use crate::math::Math; +// use crate::mipp::MippProof; +// use crate::poseidon_transcript::PoseidonTranscript; +// use crate::sqrt_pst::Polynomial; +// use crate::sumcheck::SumcheckInstanceProof; +// use crate::transcript::Transcript; +// use crate::unipoly::UniPoly; +// use ark_crypto_primitives::sponge::poseidon::PoseidonConfig; +// use ark_crypto_primitives::sponge::Absorb; +// use ark_ec::pairing::Pairing; + +// use ark_poly_commit::multilinear_pc::data_structures::{Commitment, Proof}; +// use itertools::Itertools; + +// use super::r1csinstance::R1CSInstance; + +// use super::sparse_mlpoly::{SparsePolyEntry, SparsePolynomial}; +// use super::timer::Timer; +// use ark_snark::{CircuitSpecificSetupSNARK, SNARK}; + +// use crate::ark_std::UniformRand; +// use ark_groth16::{Groth16, ProvingKey, VerifyingKey}; + +// use ark_serialize::*; +// use ark_std::{One, Zero}; + +// #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)] +// pub struct R1CSProof { +// // The PST commitment to the multilinear extension of the witness. +// pub comm: Commitment, +// sc_proof_phase1: SumcheckInstanceProof, +// claims_phase2: ( +// E::ScalarField, +// E::ScalarField, +// E::ScalarField, +// E::ScalarField, +// ), +// sc_proof_phase2: SumcheckInstanceProof, +// pub eval_vars_at_ry: E::ScalarField, +// pub proof_eval_vars_at_ry: Proof, +// rx: Vec, +// ry: Vec, +// // The transcript state after the satisfiability proof was computed. +// pub transcript_sat_state: E::ScalarField, +// pub initial_state: E::ScalarField, +// pub t: E::TargetField, +// pub mipp_proof: MippProof, +// } + +// #[derive(Debug, CanonicalSerialize, CanonicalDeserialize, Clone)] +// pub struct R1CSVerifierProof { +// comm: Commitment, +// circuit_proof: ark_groth16::Proof, +// initial_state: E::ScalarField, +// transcript_sat_state: E::ScalarField, +// eval_vars_at_ry: E::ScalarField, +// proof_eval_vars_at_ry: Proof, +// t: E::TargetField, +// mipp_proof: MippProof, +// } + +// #[derive(Clone)] +// pub struct CircuitGens { +// pk: ProvingKey, +// vk: VerifyingKey, +// } + +// impl CircuitGens +// where +// E: Pairing, +// { +// // Performs the circuit-specific setup required by Groth16 for the sumcheck +// // circuit. This is done by filling the struct with dummy elements, ensuring +// // the sizes are correct so the setup matches the circuit that will be proved. +// pub fn setup( +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// let mut rng = rand::thread_rng(); + +// let uni_polys_round1 = (0..num_cons.log_2()) +// .map(|_i| { +// UniPoly::::from_evals(&[ +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// ]) +// }) +// .collect::>>(); + +// let uni_polys_round2 = (0..num_vars.log_2() + 1) +// .map(|_i| { +// UniPoly::::from_evals(&[ +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// E::ScalarField::rand(&mut rng), +// ]) +// }) +// .collect::>>(); + +// let circuit = R1CSVerificationCircuit { +// num_vars: num_vars, +// num_cons: num_cons, +// input: (0..num_inputs) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// input_as_sparse_poly: SparsePolynomial::new( +// num_vars.log_2(), +// (0..num_inputs + 1) +// .map(|i| SparsePolyEntry::new(i, E::ScalarField::rand(&mut rng))) +// .collect::>>(), +// ), +// evals: ( +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// ), +// params: poseidon, +// prev_challenge: E::ScalarField::zero(), +// claims_phase2: ( +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// E::ScalarField::zero(), +// ), +// eval_vars_at_ry: E::ScalarField::zero(), +// sc_phase1: SumcheckVerificationCircuit { +// polys: uni_polys_round1, +// }, +// sc_phase2: SumcheckVerificationCircuit { +// polys: uni_polys_round2, +// }, +// claimed_rx: (0..num_cons.log_2()) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// claimed_ry: (0..num_vars.log_2() + 1) +// .map(|_i| E::ScalarField::rand(&mut rng)) +// .collect_vec(), +// claimed_transcript_sat_state: E::ScalarField::zero(), +// }; +// let (pk, vk) = Groth16::::setup(circuit.clone(), &mut rng).unwrap(); +// CircuitGens { pk, vk } +// } +// } + +// #[derive(Clone)] +// pub struct R1CSGens { +// gens_pc: PolyCommitmentGens, +// gens_gc: CircuitGens, +// } + +// impl R1CSGens { +// // Performs the setup for the polynomial commitment PST and for Groth16. +// pub fn setup( +// label: &'static [u8], +// num_cons: usize, +// num_vars: usize, +// num_inputs: usize, +// poseidon: PoseidonConfig, +// ) -> Self { +// let num_poly_vars = num_vars.log_2(); +// let gens_pc = PolyCommitmentGens::setup(num_poly_vars, label); +// let gens_gc = CircuitGens::setup(num_cons, num_vars, num_inputs, poseidon); +// R1CSGens { gens_pc, gens_gc } +// } +// } + +// impl R1CSProof +// where +// E: Pairing, +// E::ScalarField: Absorb, +// { +// fn prove_phase_one( +// num_rounds: usize, +// evals_tau: &mut DensePolynomial, +// evals_Az: &mut DensePolynomial, +// evals_Bz: &mut DensePolynomial, +// evals_Cz: &mut DensePolynomial, +// transcript: &mut PoseidonTranscript, +// ) -> ( +// SumcheckInstanceProof, +// Vec, +// Vec, +// ) { +// let comb_func = +// |poly_tau_comp: &E::ScalarField, +// poly_A_comp: &E::ScalarField, +// poly_B_comp: &E::ScalarField, +// poly_C_comp: &E::ScalarField| +// -> E::ScalarField { (*poly_tau_comp) * ((*poly_A_comp) * poly_B_comp - poly_C_comp) }; + +// let (sc_proof_phase_one, r, claims) = SumcheckInstanceProof::prove_cubic_with_additive_term( +// &E::ScalarField::zero(), // claim is zero +// num_rounds, +// evals_tau, +// evals_Az, +// evals_Bz, +// evals_Cz, +// comb_func, +// transcript, +// ); + +// (sc_proof_phase_one, r, claims) +// } + +// fn prove_phase_two( +// num_rounds: usize, +// claim: &E::ScalarField, +// evals_z: &mut DensePolynomial, +// evals_ABC: &mut DensePolynomial, +// transcript: &mut PoseidonTranscript, +// ) -> ( +// SumcheckInstanceProof, +// Vec, +// Vec, +// ) { +// let comb_func = |poly_A_comp: &E::ScalarField, +// poly_B_comp: &E::ScalarField| +// -> E::ScalarField { (*poly_A_comp) * poly_B_comp }; +// let (sc_proof_phase_two, r, claims) = SumcheckInstanceProof::prove_quad( +// claim, num_rounds, evals_z, evals_ABC, comb_func, transcript, +// ); + +// (sc_proof_phase_two, r, claims) +// } + +// // Proves the R1CS instance inst is satisfiable given the assignment +// // vars. +// pub fn prove( +// inst: &R1CSInstance, +// vars: Vec, +// input: &[E::ScalarField], +// gens: &R1CSGens, +// transcript: &mut PoseidonTranscript, +// ) -> (Self, Vec, Vec) { +// let timer_prove = Timer::new("R1CSProof::prove"); +// // we currently require the number of |inputs| + 1 to be at most number of vars +// assert!(input.len() < vars.len()); + +// // create the multilinear witness polynomial from the satisfying assiment +// // expressed as the list of sqrt-sized polynomials +// let mut pl = Polynomial::from_evaluations(&vars.clone()); + +// let timer_commit = Timer::new("polycommit"); + +// // commitment list to the satisfying witness polynomial list +// let (comm_list, t) = pl.commit(&gens.gens_pc.ck); + +// transcript.append_gt::(b"", &t); + +// timer_commit.stop(); + +// let initial_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&initial_state); + +// transcript.append_scalar_vector(b"", &input); + +// let timer_sc_proof_phase1 = Timer::new("prove_sc_phase_one"); + +// // append input to variables to create a single vector z +// let z = { +// let num_inputs = input.len(); +// let num_vars = vars.len(); +// let mut z = vars; +// z.extend(&vec![E::ScalarField::one()]); // add constant term in z +// z.extend(input); +// z.extend(&vec![E::ScalarField::zero(); num_vars - num_inputs - 1]); // we will pad with zeros +// z +// }; + +// // derive the verifier's challenge tau +// let (num_rounds_x, num_rounds_y) = (inst.get_num_cons().log_2(), z.len().log_2()); +// let tau = transcript.challenge_scalar_vec(b"", num_rounds_x); +// // compute the initial evaluation table for R(\tau, x) +// let mut poly_tau = DensePolynomial::new(EqPolynomial::new(tau).evals()); +// let (mut poly_Az, mut poly_Bz, mut poly_Cz) = +// inst.multiply_vec(inst.get_num_cons(), z.len(), &z); + +// let (sc_proof_phase1, rx, _claims_phase1) = R1CSProof::::prove_phase_one( +// num_rounds_x, +// &mut poly_tau, +// &mut poly_Az, +// &mut poly_Bz, +// &mut poly_Cz, +// transcript, +// ); +// assert_eq!(poly_tau.len(), 1); +// assert_eq!(poly_Az.len(), 1); +// assert_eq!(poly_Bz.len(), 1); +// assert_eq!(poly_Cz.len(), 1); +// timer_sc_proof_phase1.stop(); + +// let (tau_claim, Az_claim, Bz_claim, Cz_claim) = +// (&poly_tau[0], &poly_Az[0], &poly_Bz[0], &poly_Cz[0]); +// let prod_Az_Bz_claims = (*Az_claim) * Bz_claim; + +// // prove the final step of sum-check #1 +// let taus_bound_rx = tau_claim; +// let _claim_post_phase1 = ((*Az_claim) * Bz_claim - Cz_claim) * taus_bound_rx; + +// let timer_sc_proof_phase2 = Timer::new("prove_sc_phase_two"); +// // combine the three claims into a single claim +// let r_A: E::ScalarField = transcript.challenge_scalar(b""); +// let r_B: E::ScalarField = transcript.challenge_scalar(b""); +// let r_C: E::ScalarField = transcript.challenge_scalar(b""); +// let claim_phase2 = r_A * Az_claim + r_B * Bz_claim + r_C * Cz_claim; + +// let evals_ABC = { +// // compute the initial evaluation table for R(\tau, x) +// let evals_rx = EqPolynomial::new(rx.clone()).evals(); +// let (evals_A, evals_B, evals_C) = +// inst.compute_eval_table_sparse(inst.get_num_cons(), z.len(), &evals_rx); + +// assert_eq!(evals_A.len(), evals_B.len()); +// assert_eq!(evals_A.len(), evals_C.len()); +// (0..evals_A.len()) +// .map(|i| r_A * evals_A[i] + r_B * evals_B[i] + r_C * evals_C[i]) +// .collect::>() +// }; + +// // another instance of the sum-check protocol +// let (sc_proof_phase2, ry, _claims_phase2) = R1CSProof::::prove_phase_two( +// num_rounds_y, +// &claim_phase2, +// &mut DensePolynomial::new(z), +// &mut DensePolynomial::new(evals_ABC), +// transcript, +// ); +// timer_sc_proof_phase2.stop(); +// let transcript_sat_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&transcript_sat_state); + +// let timmer_opening = Timer::new("polyopening"); + +// let (comm, proof_eval_vars_at_ry, mipp_proof) = +// pl.open(transcript, comm_list, &gens.gens_pc.ck, &ry[1..], &t); + +// timmer_opening.stop(); + +// let timer_polyeval = Timer::new("polyeval"); +// let eval_vars_at_ry = pl.eval(&ry[1..]); +// timer_polyeval.stop(); +// timer_prove.stop(); +// ( +// R1CSProof { +// comm, +// initial_state, +// sc_proof_phase1, +// claims_phase2: (*Az_claim, *Bz_claim, *Cz_claim, prod_Az_Bz_claims), +// sc_proof_phase2, +// eval_vars_at_ry, +// proof_eval_vars_at_ry, +// rx: rx.clone(), +// ry: ry.clone(), +// transcript_sat_state, +// t, +// mipp_proof, +// }, +// rx, +// ry, +// ) +// } + +// // Creates a Groth16 proof for the verification of sumcheck, expressed +// // as a circuit. +// pub fn prove_verifier( +// &self, +// num_vars: usize, +// num_cons: usize, +// input: &[E::ScalarField], +// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), +// transcript: &mut PoseidonTranscript, +// gens: &R1CSGens, +// poseidon: PoseidonConfig, +// ) -> Result, ProofVerifyError> { +// // serialise and add the IPP commitment to the transcript +// transcript.append_gt::(b"", &self.t); + +// let initial_state = transcript.challenge_scalar(b""); +// transcript.new_from_state(&initial_state); + +// let mut input_as_sparse_poly_entries = vec![SparsePolyEntry::new(0, E::ScalarField::one())]; +// //remaining inputs +// input_as_sparse_poly_entries.extend( +// (0..input.len()) +// .map(|i| SparsePolyEntry::new(i + 1, input[i])) +// .collect::>>(), +// ); +// let input_as_sparse_poly = +// SparsePolynomial::new(num_vars.log_2() as usize, input_as_sparse_poly_entries); + +// let config = VerifierConfig { +// num_vars, +// num_cons, +// input: input.to_vec(), +// evals: *evals, +// params: poseidon, +// prev_challenge: initial_state, +// claims_phase2: self.claims_phase2, +// polys_sc1: self.sc_proof_phase1.polys.clone(), +// polys_sc2: self.sc_proof_phase2.polys.clone(), +// eval_vars_at_ry: self.eval_vars_at_ry, +// input_as_sparse_poly, +// comm: self.comm.clone(), +// rx: self.rx.clone(), +// ry: self.ry.clone(), +// transcript_sat_state: self.transcript_sat_state, +// }; + +// let circuit = R1CSVerificationCircuit::new(&config); + +// let circuit_prover_timer = Timer::new("provecircuit"); +// let proof = Groth16::::prove(&gens.gens_gc.pk, circuit, &mut rand::thread_rng()).unwrap(); +// circuit_prover_timer.stop(); + +// Ok(R1CSVerifierProof { +// comm: self.comm.clone(), +// circuit_proof: proof, +// initial_state: self.initial_state, +// transcript_sat_state: self.transcript_sat_state, +// eval_vars_at_ry: self.eval_vars_at_ry, +// proof_eval_vars_at_ry: self.proof_eval_vars_at_ry.clone(), +// t: self.t, +// mipp_proof: self.mipp_proof.clone(), +// }) +// } +// } + +// impl R1CSVerifierProof +// where +// ::ScalarField: Absorb, +// { +// // Verifier the Groth16 proof for the sumcheck circuit and the PST polynomial +// // commitment opening. +// pub fn verify( +// &self, +// r: (Vec, Vec), +// input: &[E::ScalarField], +// evals: &(E::ScalarField, E::ScalarField, E::ScalarField), +// transcript: &mut PoseidonTranscript, +// gens: &R1CSGens, +// ) -> Result { +// let (rx, ry) = &r; +// let (Ar, Br, Cr) = evals; +// let mut pubs = vec![self.initial_state]; +// pubs.extend(input.clone()); +// pubs.extend(rx.clone()); +// pubs.extend(ry.clone()); +// pubs.extend(vec![ +// self.eval_vars_at_ry, +// *Ar, +// *Br, +// *Cr, +// self.transcript_sat_state, +// ]); +// transcript.new_from_state(&self.transcript_sat_state); +// par! { +// // verifies the Groth16 proof for the spartan verifier +// let is_verified = Groth16::::verify(&gens.gens_gc.vk, &pubs, &self.circuit_proof).unwrap(), + +// // verifies the proof of opening against the result of evaluating the +// // witness polynomial at point ry +// let res = Polynomial::verify( +// transcript, +// &gens.gens_pc.vk, +// &self.comm, +// &ry[1..], +// self.eval_vars_at_ry, +// &self.proof_eval_vars_at_ry, +// &self.mipp_proof, +// &self.t, +// ) +// }; +// assert!(is_verified == true); +// assert!(res == true); +// Ok(is_verified && res) +// } +// } // #[cfg(test)] // mod tests { // use super::*; -// use ark_ec::CurveGroup; -// use ark_ff::Field; -// use ark_r1cs_std::pairing::PairingVar; -// // use crate::verifier_circuit::VerifierCircuit; -// type BasePrimeField = <<::G1 as CurveGroup>::BaseField as Field>::BasePrimeField; + // use ark_ff::PrimeField; // use ark_std::UniformRand; -// use ark_relations::r1cs::ConstraintSystem; // type F = ark_bls12_377::Fr; -// use crate::{rand::SeedableRng, parameters::get_bls12377_fq_params}; -// use ark_relations::r1cs::ConstraintSynthesizer; // fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { // // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 @@ -575,31 +566,27 @@ where // } // use crate::parameters::PoseidonConfiguration; -// //#[test] -// // fn check_r1cs_proof_ark_blst() { -// // let params = ark_blst::Scalar::poseidon_params(); -// // check_r1cs_proof::(params); -// // } +// #[test] +// fn check_r1cs_proof_ark_blst() { +// let params = ark_blst::Scalar::poseidon_params(); +// check_r1cs_proof::(params); +// } // #[test] // fn check_r1cs_proof_bls12_377() { // let params = ark_bls12_377::Fr::poseidon_params(); -// check_r1cs_proof::(params); +// check_r1cs_proof::(params); // } -// //#[test -// // fn check_r1cs_proof_bls12_381() { -// // let params = ark_bls12_381::Fr::poseidon_params(); -// // check_r1cs_proof::(params); -// // } -// fn check_r1cs_proof(params: PoseidonConfig) +// #[test] +// fn check_r1cs_proof_bls12_381() { +// let params = ark_bls12_381::Fr::poseidon_params(); +// check_r1cs_proof::(params); +// } +// fn check_r1cs_proof

(params: PoseidonConfig) // where // P: Pairing, -// IV: PairingVar>, -// P::BaseField: PrimeField, -// P::BaseField: Absorb, // P::ScalarField: PrimeField, // P::ScalarField: Absorb, - // { // let num_vars = 1024; // let num_cons = num_vars; @@ -612,14 +599,14 @@ where // //let params = poseidon_params(); // // let mut random_tape = RandomTape::new(b"proof"); -// let mut prover_transcript = PoseidonTranscript::new(¶ms_to_base_field::

()); +// let mut prover_transcript = PoseidonTranscript::new(¶ms.clone()); // let c = prover_transcript.challenge_scalar::(b""); -// prover_transcript.new_from_state2(&c); +// prover_transcript.new_from_state(&c); // let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); // let inst_evals = inst.evaluate(&rx, &ry); -// prover_transcript.new_from_state2(&c); +// prover_transcript.new_from_state(&c); // let verifer_proof = proof // .prove_verifier( // num_vars, @@ -633,170 +620,14 @@ where // .unwrap(); // let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); -// // assert!(verifer_proof -// // .verify( -// // (rx, ry), -// // &input, -// // &inst_evals, -// // &mut verifier_transcript, -// // &gens -// // ) -// // .is_ok()); -// // let mut rng = rand_chacha::ChaChaRng::seed_from_u64(1776); -// // let cs = ConstraintSystem::>::new_ref(); -// // let circuit = VerifierCircuit::::new((rx, ry),input,inst_evals,verifier_transcript,gens,verifer_proof).unwrap(); -// // circuit.generate_constraints(cs.clone()); -// // // .unwrap(); -// // assert!(cs.is_satisfied().unwrap()); - +// assert!(verifer_proof +// .verify( +// (rx, ry), +// &input, +// &inst_evals, +// &mut verifier_transcript, +// &gens +// ) +// .is_ok()); // } // } - - -#[cfg(test)] -mod tests { - - use super::*; - - use ark_ff::PrimeField; - use ark_std::UniformRand; - type F = ark_bls12_377::Fr; - - fn produce_tiny_r1cs() -> (R1CSInstance, Vec, Vec) { - // three constraints over five variables Z1, Z2, Z3, Z4, and Z5 - // rounded to the nearest power of two - let num_cons = 128; - let num_vars = 256; - let num_inputs = 2; - - // encode the above constraints into three matrices - let mut A: Vec<(usize, usize, F)> = Vec::new(); - let mut B: Vec<(usize, usize, F)> = Vec::new(); - let mut C: Vec<(usize, usize, F)> = Vec::new(); - - let one = F::one(); - // constraint 0 entries - // (Z1 + Z2) * I0 - Z3 = 0; - A.push((0, 0, one)); - A.push((0, 1, one)); - B.push((0, num_vars + 1, one)); - C.push((0, 2, one)); - - // constraint 1 entries - // (Z1 + I1) * (Z3) - Z4 = 0 - A.push((1, 0, one)); - A.push((1, num_vars + 2, one)); - B.push((1, 2, one)); - C.push((1, 3, one)); - // constraint 3 entries - // Z5 * 1 - 0 = 0 - A.push((2, 4, one)); - B.push((2, num_vars, one)); - - let inst = R1CSInstance::new(num_cons, num_vars, num_inputs, &A, &B, &C); - - // compute a satisfying assignment - let mut rng = ark_std::rand::thread_rng(); - let i0 = F::rand(&mut rng); - let i1 = F::rand(&mut rng); - let z1 = F::rand(&mut rng); - let z2 = F::rand(&mut rng); - let z3 = (z1 + z2) * i0; // constraint 1: (Z1 + Z2) * I0 - Z3 = 0; - let z4 = (z1 + i1) * z3; // constraint 2: (Z1 + I1) * (Z3) - Z4 = 0 - let z5 = F::zero(); //constraint 3 - - let mut vars = vec![F::zero(); num_vars]; - vars[0] = z1; - vars[1] = z2; - vars[2] = z3; - vars[3] = z4; - vars[4] = z5; - - let mut input = vec![F::zero(); num_inputs]; - input[0] = i0; - input[1] = i1; - - (inst, vars, input) - } - - #[test] - fn test_tiny_r1cs() { - let (inst, vars, input) = tests::produce_tiny_r1cs(); - let is_sat = inst.is_sat(&vars, &input); - assert!(is_sat); - } - - #[test] - fn test_synthetic_r1cs() { - type F = ark_bls12_377::Fr; - let (inst, vars, input) = R1CSInstance::::produce_synthetic_r1cs(1024, 1024, 10); - let is_sat = inst.is_sat(&vars, &input); - assert!(is_sat); - } - - use crate::parameters::PoseidonConfiguration; - #[test] - fn check_r1cs_proof_ark_blst() { - let params = ark_blst::Scalar::poseidon_params(); - check_r1cs_proof::(params); - } - #[test] - fn check_r1cs_proof_bls12_377() { - let params = ark_bls12_377::Fr::poseidon_params(); - check_r1cs_proof::(params); - } - - #[test] - fn check_r1cs_proof_bls12_381() { - let params = ark_bls12_381::Fr::poseidon_params(); - check_r1cs_proof::(params); - } - fn check_r1cs_proof

(params: PoseidonConfig) - where - P: Pairing, - P::ScalarField: PrimeField, - P::ScalarField: Absorb, - { - let num_vars = 1024; - let num_cons = num_vars; - let num_inputs = 3; - let (inst, vars, input) = - R1CSInstance::::produce_synthetic_r1cs(num_cons, num_vars, num_inputs); - - let gens = R1CSGens::

::setup(b"test-m", num_cons, num_vars, num_inputs, params.clone()); - - //let params = poseidon_params(); - // let mut random_tape = RandomTape::new(b"proof"); - - let mut prover_transcript = PoseidonTranscript::new(¶ms_to_base_field::

()); - let c = prover_transcript.challenge_scalar::(b""); - prover_transcript.new_from_state2(&c); - let (proof, rx, ry) = R1CSProof::prove(&inst, vars, &input, &gens, &mut prover_transcript); - - let inst_evals = inst.evaluate(&rx, &ry); - - prover_transcript.new_from_state2(&c); - let verifer_proof = proof - .prove_verifier( - num_vars, - num_cons, - &input, - &inst_evals, - &mut prover_transcript, - &gens, - params.clone(), - ) - .unwrap(); - - let mut verifier_transcript = PoseidonTranscript::new(¶ms.clone()); - assert!(verifer_proof - .verify( - (rx, ry), - &input, - &inst_evals, - &mut verifier_transcript, - &gens - ) - .is_ok()); - } -} \ No newline at end of file diff --git a/src/sqrt_pst.rs b/src/sqrt_pst.rs index 61a865a2..82774ece 100644 --- a/src/sqrt_pst.rs +++ b/src/sqrt_pst.rs @@ -267,7 +267,7 @@ impl Polynomial { #[cfg(test)] mod tests { - use crate::parameters::{get_bls12377_fq_params, poseidon_params}; + use crate::parameters::{get_bls12377_fq_params}; use super::*; type F = ark_bls12_377::Fr; @@ -321,12 +321,12 @@ mod tests { let (comm_list, t) = pl.commit(&ck); - let params = poseidon_params(); - let mut prover_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + let params = get_bls12377_fq_params(); + let mut prover_transcript = PoseidonTranscript::new(¶ms); let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let mut verifier_transcript = PoseidonTranscript::new(&get_bls12377_fq_params()); + let mut verifier_transcript = PoseidonTranscript::new(¶ms); let res = Polynomial::verify( &mut verifier_transcript, diff --git a/src/sumcheck.rs b/src/sumcheck.rs index 6dcc9f51..e43232a1 100644 --- a/src/sumcheck.rs +++ b/src/sumcheck.rs @@ -7,7 +7,6 @@ use crate::transcript::Transcript; use super::unipoly::UniPoly; use ark_crypto_primitives::sponge::Absorb; -use ark_ec::PairingFriendlyCycle; use ark_ff::PrimeField; use ark_serialize::*; @@ -441,4 +440,4 @@ impl SumcheckInstanceProof { vec![poly_A[0], poly_B[0]], ) } -} \ No newline at end of file +} From ba0e9fc412be08fb7001dc1d3efcc6e84a570590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rosario=20Cannav=C3=B2?= Date: Wed, 13 Dec 2023 11:23:02 +0100 Subject: [PATCH 19/21] fix: changed number of params in benchmark --- Cargo.toml | 4 + benches/pst.rs | 197 ++++++++++++++++++++-------------------- benches/testudo_comm.rs | 7 +- 3 files changed, 107 insertions(+), 101 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8ad4f6c2..66f6352f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,10 @@ harness = false name = "pst" harness = false +[[bench]] +name = "testudo_comm" +harness = false + [features] multicore = ["rayon"] profile = [] diff --git a/benches/pst.rs b/benches/pst.rs index a9b821a0..ea9727b2 100644 --- a/benches/pst.rs +++ b/benches/pst.rs @@ -1,98 +1,99 @@ -use std::time::Instant; - -use ark_poly_commit::multilinear_pc::MultilinearPC; -use ark_serialize::CanonicalSerialize; -use libtestudo::{ - parameters::PoseidonConfiguration, poseidon_transcript::PoseidonTranscript, sqrt_pst::Polynomial, -}; -use serde::Serialize; -type F = ark_bls12_377::Fr; -type E = ark_bls12_377::Bls12_377; -use ark_std::UniformRand; - -#[derive(Default, Clone, Serialize)] -struct BenchmarkResults { - power: usize, - commit_time: u128, - opening_time: u128, - verification_time: u128, - proof_size: usize, - commiter_key_size: usize, -} -fn main() { - let params = ark_bls12_377::Fr::poseidon_params(); - - let mut writer = csv::Writer::from_path("sqrt_pst.csv").expect("unable to open csv writer"); - for &s in [4, 5, 20, 27].iter() { - println!("Running for {} inputs", s); - let mut rng = ark_std::test_rng(); - let mut br = BenchmarkResults::default(); - br.power = s; - let num_vars = s; - let len = 2_usize.pow(num_vars as u32); - let z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); - let r: Vec = (0..num_vars) - .into_iter() - .map(|_| F::rand(&mut rng)) - .collect(); - - let setup_vars = (num_vars as f32 / 2.0).ceil() as usize; - let gens = MultilinearPC::::setup((num_vars as f32 / 2.0).ceil() as usize, &mut rng); - let (ck, vk) = MultilinearPC::::trim(&gens, setup_vars); - - let mut cks = Vec::::new(); - ck.serialize_with_mode(&mut cks, ark_serialize::Compress::Yes) - .unwrap(); - br.commiter_key_size = cks.len(); - - let mut pl = Polynomial::from_evaluations(&z.clone()); - - let v = pl.eval(&r); - - let start = Instant::now(); - let (comm_list, t) = pl.commit(&ck); - let duration = start.elapsed().as_millis(); - br.commit_time = duration; - - let mut prover_transcript = PoseidonTranscript::new(¶ms); - - let start = Instant::now(); - let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); - let duration = start.elapsed().as_millis(); - br.opening_time = duration; - - let mut p1 = Vec::::new(); - let mut p2 = Vec::::new(); - pst_proof - .serialize_with_mode(&mut p1, ark_serialize::Compress::Yes) - .unwrap(); - - mipp_proof - .serialize_with_mode(&mut p2, ark_serialize::Compress::Yes) - .unwrap(); - - br.proof_size = p1.len() + p2.len(); - - let mut verifier_transcript = PoseidonTranscript::new(¶ms); - - let start = Instant::now(); - let res = Polynomial::verify( - &mut verifier_transcript, - &vk, - &u, - &r, - v, - &pst_proof, - &mipp_proof, - &t, - ); - let duration = start.elapsed().as_millis(); - br.verification_time = duration; - assert!(res == true); - - writer - .serialize(br) - .expect("unable to write results to csv"); - writer.flush().expect("wasn't able to flush"); - } -} +// use std::time::Instant; + +// use ark_poly_commit::multilinear_pc::MultilinearPC; +// use ark_serialize::CanonicalSerialize; +// use libtestudo::{ +// parameters::PoseidonConfiguration, poseidon_transcript::PoseidonTranscript, sqrt_pst::Polynomial, +// }; +// use serde::Serialize; +// type F = ark_bls12_377::Fr; +// type E = ark_bls12_377::Bls12_377; +// use ark_std::UniformRand; + +// #[derive(Default, Clone, Serialize)] +// struct BenchmarkResults { +// power: usize, +// commit_time: u128, +// opening_time: u128, +// verification_time: u128, +// proof_size: usize, +// commiter_key_size: usize, +// } +// fn main() { +// let params = ark_bls12_377::Fr::poseidon_params(); + +// let mut writer = csv::Writer::from_path("sqrt_pst.csv").expect("unable to open csv writer"); +// for &s in [4, 5, 20, 27].iter() { +// println!("Running for {} inputs", s); +// let mut rng = ark_std::test_rng(); +// let mut br = BenchmarkResults::default(); +// br.power = s; +// let num_vars = s; +// let len = 2_usize.pow(num_vars as u32); +// let z: Vec = (0..len).into_iter().map(|_| F::rand(&mut rng)).collect(); +// let r: Vec = (0..num_vars) +// .into_iter() +// .map(|_| F::rand(&mut rng)) +// .collect(); + +// let setup_vars = (num_vars as f32 / 2.0).ceil() as usize; +// let gens = MultilinearPC::::setup((num_vars as f32 / 2.0).ceil() as usize, &mut rng); +// let (ck, vk) = MultilinearPC::::trim(&gens, setup_vars); + +// let mut cks = Vec::::new(); +// ck.serialize_with_mode(&mut cks, ark_serialize::Compress::Yes) +// .unwrap(); +// br.commiter_key_size = cks.len(); + +// let mut pl = Polynomial::from_evaluations(&z.clone()); + +// let v = pl.eval(&r); + +// let start = Instant::now(); +// let (comm_list, t) = pl.commit(&ck); +// let duration = start.elapsed().as_millis(); +// br.commit_time = duration; + +// let mut prover_transcript = PoseidonTranscript::new(¶ms); + +// let start = Instant::now(); +// let (u, pst_proof, mipp_proof) = pl.open(&mut prover_transcript, comm_list, &ck, &r, &t); +// let duration = start.elapsed().as_millis(); +// br.opening_time = duration; + +// let mut p1 = Vec::::new(); +// let mut p2 = Vec::::new(); +// pst_proof +// .serialize_with_mode(&mut p1, ark_serialize::Compress::Yes) +// .unwrap(); + +// mipp_proof +// .serialize_with_mode(&mut p2, ark_serialize::Compress::Yes) +// .unwrap(); + +// br.proof_size = p1.len() + p2.len(); + +// let mut verifier_transcript = PoseidonTranscript::new(¶ms); + +// let start = Instant::now(); +// let res = Polynomial::verify( +// &mut verifier_transcript, +// &vk, +// &u, +// &r, +// v, +// &pst_proof, +// &mipp_proof, +// &t, +// ); +// let duration = start.elapsed().as_millis(); +// br.verification_time = duration; +// assert!(res == true); + +// writer +// .serialize(br) +// .expect("unable to write results to csv"); +// writer.flush().expect("wasn't able to flush"); +// } +// } +fn main() {} diff --git a/benches/testudo_comm.rs b/benches/testudo_comm.rs index 75c205b8..673c402d 100644 --- a/benches/testudo_comm.rs +++ b/benches/testudo_comm.rs @@ -21,8 +21,8 @@ struct BenchmarkResults { fn main() { let params = get_bls12377_fq_params(); - let mut writer = csv::Writer::from_path("sqrt_pst.csv").expect("unable to open csv writer"); - for &s in [4, 5, 20, 27].iter() { + let mut writer = csv::Writer::from_path("testudo_comm.csv").expect("unable to open csv writer"); + for &s in [5, 10, 15, 20, 25].iter() { println!("Running for {} inputs", s); let mut rng = ark_std::test_rng(); let mut br = BenchmarkResults::default(); @@ -51,7 +51,7 @@ fn main() { let circuit = TestudoCommVerifier:: { - &get_bls12377_fq_params(), + params: get_bls12377_fq_params(), vk, U: u, point: r, @@ -66,6 +66,7 @@ fn main() { assert!(cs.is_satisfied().unwrap()); br.num_constraints = cs.num_constraints(); + writer .serialize(br) .expect("unable to write results to csv"); From e289942b2b20f3ef543d8500c6b8221273ee0a4c Mon Sep 17 00:00:00 2001 From: mariobenissimo Date: Thu, 14 Dec 2023 18:08:08 +0100 Subject: [PATCH 20/21] fix: Error AssignmentMissing in circuit variable --- src/circuit_verifier.rs | 85 +++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/src/circuit_verifier.rs b/src/circuit_verifier.rs index 46553ee2..60cde505 100644 --- a/src/circuit_verifier.rs +++ b/src/circuit_verifier.rs @@ -117,7 +117,7 @@ where let mut point_var = Vec::new(); for p in self.point.clone().into_iter() { let p_var = - NonNativeFieldVar::::new_input(cs.clone(), || Ok(p))?; + NonNativeFieldVar::::new_witness(cs.clone(), || Ok(p))?; point_var.push(p_var); } let len = point_var.len(); @@ -162,15 +162,15 @@ where IV::G2Var: CurveVar, IV::GTVar: FieldVar, { - let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; - let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; + let vk_g_var = IV::G1Var::new_witness(cs.clone(), || Ok(vk.g))?; + let vk_h_var = IV::G2Var::new_witness(cs.clone(), || Ok(vk.h))?; let mut vk_gmask_var = Vec::new(); for g_mask in vk.g_mask_random.clone().into_iter() { - let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; + let g_mask_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_mask))?; vk_gmask_var.push(g_mask_var); } // allocate commitment - let com_h_prod_var = IV::G2Var::new_input(cs.clone(), || Ok(commitment.h_product))?; + let com_h_prod_var = IV::G2Var::new_witness(cs.clone(), || Ok(commitment.h_product))?; let pair_right_op = com_h_prod_var - (vk_h_var @@ -191,7 +191,7 @@ where let h_mask_random = vk.h_mask_random[vk.nv - point_var.len()..].to_vec(); let mut h_mask_random_var = Vec::new(); for h_mask in h_mask_random.clone().into_iter() { - let h_mask_var = IV::G2Var::new_input(cs.clone(), || Ok(h_mask))?; + let h_mask_var = IV::G2Var::new_witness(cs.clone(), || Ok(h_mask))?; h_mask_random_var.push(h_mask_var); } let pairing_rights_var: Vec<_> = (0..point_var.len()) @@ -204,7 +204,7 @@ where .collect(); let mut proofs_var = Vec::new(); for p in proof.proofs.clone().into_iter() { - let proof_var = IV::G1Var::new_input(cs.clone(), || Ok(p))?; + let proof_var = IV::G1Var::new_witness(cs.clone(), || Ok(p))?; proofs_var.push(proof_var); } let pairing_lefts_var: Vec = proofs_var @@ -232,18 +232,18 @@ where IV::G2Var: CurveVar, IV::GTVar: FieldVar, { - let vk_g_var = IV::G1Var::new_input(cs.clone(), || Ok(vk.g))?; - let vk_h_var = IV::G2Var::new_input(cs.clone(), || Ok(vk.h))?; + let vk_g_var = IV::G1Var::new_witness(cs.clone(), || Ok(vk.g))?; + let vk_h_var = IV::G2Var::new_witness(cs.clone(), || Ok(vk.h))?; let mut vk_gmask_var = Vec::new(); for g_mask in vk.g_mask_random.clone().into_iter() { - let g_mask_var = IV::G1Var::new_input(cs.clone(), || Ok(g_mask))?; + let g_mask_var = IV::G1Var::new_witness(cs.clone(), || Ok(g_mask))?; vk_gmask_var.push(g_mask_var); } // allocate commitment - let com_g1_prod_var = IV::G1Var::new_input(cs.clone(), || Ok(commitment.g_product))?; + let com_g1_prod_var = IV::G1Var::new_witness(cs.clone(), || Ok(commitment.g_product))?; let value_var = - NonNativeFieldVar::::new_input(cs.clone(), || Ok(value))?; + NonNativeFieldVar::::new_witness(cs.clone(), || Ok(value))?; // allocate proof let mut proofs_var = Vec::new(); @@ -299,17 +299,19 @@ where IV::G2Var: CurveVar, IV::GTVar: FieldVar, { + let comms_u = proof.comms_u.clone(); + let comms_t = proof.comms_t.clone(); let mut comms_u_var = Vec::new(); for (first, second) in proof.comms_u.clone().into_iter() { - let first_var = IV::G1Var::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::G1Var::new_input(cs.clone(), || Ok(second))?; + let first_var = IV::G1Var::new_witness(cs.clone(), || Ok(first))?; + let second_var = IV::G1Var::new_witness(cs.clone(), || Ok(second))?; comms_u_var.push((first_var, second_var)); } // allocate comms_t let mut comms_t_var = Vec::new(); for (first, second) in proof.comms_t.clone().into_iter() { - let first_var = IV::GTVar::new_input(cs.clone(), || Ok(first))?; - let second_var = IV::GTVar::new_input(cs.clone(), || Ok(second))?; + let first_var = IV::GTVar::new_witness(cs.clone(), || Ok(first))?; + let second_var = IV::GTVar::new_witness(cs.clone(), || Ok(second))?; comms_t_var.push((first_var, second_var)); } @@ -321,9 +323,9 @@ where NonNativeFieldVar::::new_witness(cs.clone(), || Ok(final_y))?; // start allocate T - let T_var = IV::GTVar::new_input(cs.clone(), || Ok(T))?; + let T_var = IV::GTVar::new_witness(cs.clone(), || Ok(T))?; // start allocate U.g_product - let U_g_product_var = IV::G1Var::new_input(cs.clone(), || Ok(U))?; + let U_g_product_var = IV::G1Var::new_witness(cs.clone(), || Ok(U))?; let mut final_res_var: MippTUVar = MippTUVar { tc: T_var.clone(), @@ -341,74 +343,64 @@ where let mut u_var_vec: Vec> = Vec::new(); for el in buf { - u_var_vec.push(UInt8::new_input(cs.clone(), || Ok(el))?); + u_var_vec.push(UInt8::new_witness(cs.clone(), || Ok(el))?); } transcript_var.absorb(&u_var_vec)?; - let one_var = NonNativeFieldVar::::new_input(cs.clone(), || { + let one_var = NonNativeFieldVar::::new_witness(cs.clone(), || { Ok(E::ScalarField::one()) })?; - for (i, (comm_u, comm_t)) in comms_u_var.iter().zip(comms_t_var.iter()).enumerate() { + for (i, (comm_u, comm_t)) in comms_u.iter().zip(comms_t.iter()).enumerate() { let (comm_u_l, comm_u_r) = comm_u; let (comm_t_l, comm_t_r) = comm_t; // Fiat-Shamir challenge // ABSORB COMM_U_L let mut comm_u_l_buf = Vec::new(); comm_u_l - .value() - .unwrap() - .into_affine() .serialize_with_mode(&mut comm_u_l_buf, Compress::No) .expect("serialization failed"); let mut comm_u_l_var_bytes = Vec::new(); for b in comm_u_l_buf { - comm_u_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + comm_u_l_var_bytes.push(UInt8::new_witness(cs.clone(), || Ok(b))?); } transcript_var.absorb(&comm_u_l_var_bytes)?; // ABSORB COMM_U_R let mut comm_u_r_buf = Vec::new(); comm_u_r - .value() - .unwrap() - .into_affine() .serialize_with_mode(&mut comm_u_r_buf, Compress::No) .expect("serialization failed"); let mut comm_u_r_var_bytes = Vec::new(); for b in comm_u_r_buf { - comm_u_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + comm_u_r_var_bytes.push(UInt8::new_witness(cs.clone(), || Ok(b))?); } transcript_var.absorb(&comm_u_r_var_bytes)?; // ABSORB COMM_T_L let mut comm_t_l_buf = Vec::new(); comm_t_l - .value() - .unwrap() .serialize_with_mode(&mut comm_t_l_buf, Compress::No) .expect("serialization failed"); let mut comm_t_l_var_bytes = Vec::new(); for b in comm_t_l_buf { - comm_t_l_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + comm_t_l_var_bytes.push(UInt8::new_witness(cs.clone(), || Ok(b))?); } transcript_var.absorb(&comm_t_l_var_bytes)?; // ABSORB COMM_T_R let mut comm_t_r_buf = Vec::new(); comm_t_r - .value() - .unwrap() .serialize_with_mode(&mut comm_t_r_buf, Compress::No) .expect("serialization failed"); let mut comm_t_r_var_bytes = Vec::new(); for b in comm_t_r_buf { - comm_t_r_var_bytes.push(UInt8::new_input(cs.clone(), || Ok(b))?); + comm_t_r_var_bytes.push(UInt8::new_witness(cs.clone(), || Ok(b))?); } transcript_var.absorb(&comm_t_r_var_bytes)?; @@ -494,12 +486,12 @@ where v_var, &proof.pst_proof_h, )?; - let final_a_var = IV::G1Var::new_input(cs.clone(), || Ok(proof.final_a))?; + let final_a_var = IV::G1Var::new_witness(cs.clone(), || Ok(proof.final_a))?; let final_u_var = final_a_var .scalar_mul_le(final_y_var.to_bits_le().unwrap().iter()) .unwrap(); - let final_h_var = IV::G2Var::new_input(cs.clone(), || Ok(proof.final_h))?; + let final_h_var = IV::G2Var::new_witness(cs.clone(), || Ok(proof.final_h))?; let final_u_var_prep = IV::prepare_g1(&final_a_var)?; let final_h_var_prep = IV::prepare_g2(&final_h_var)?; @@ -530,6 +522,10 @@ mod tests { use ark_poly_commit::multilinear_pc::MultilinearPC; use crate::parameters::get_bls12377_fq_params; use crate::poseidon_transcript::PoseidonTranscript; + use ark_groth16::Groth16; + use crate::rand::SeedableRng; + use ark_crypto_primitives::snark::SNARK; + use rand::rngs::OsRng; #[test] fn check_commit() { @@ -586,9 +582,16 @@ mod tests { T: t, _iv: PhantomData, }; - let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - circuit.generate_constraints(cs.clone()).unwrap(); - println!("Num constraints2: {:?}", cs.num_constraints()); - assert!(cs.is_satisfied().unwrap()); + // let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); + // circuit.generate_constraints(cs.clone()).unwrap(); + // println!("Num constraints2: {:?}", cs.num_constraints()); + // assert!(cs.is_satisfied().unwrap()); + + + let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); + let (pk, vk) = Groth16::::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); + let proof = Groth16::::prove(&pk, circuit.clone(), &mut OsRng).unwrap(); + let ok = Groth16::::verify(&pk.vk, &[], &proof).unwrap(); + assert!(ok); } } From bcd3c8b1fb355cd92ecb77893882a5943ce94861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rosario=20Cannav=C3=B2?= Date: Thu, 14 Dec 2023 19:41:33 +0100 Subject: [PATCH 21/21] feat: added groth16 proof generation time bench --- benches/testudo_comm.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/benches/testudo_comm.rs b/benches/testudo_comm.rs index 673c402d..e011373d 100644 --- a/benches/testudo_comm.rs +++ b/benches/testudo_comm.rs @@ -3,6 +3,7 @@ use libtestudo::circuit_verifier::TestudoCommVerifier; use libtestudo::{ parameters::get_bls12377_fq_params, poseidon_transcript::PoseidonTranscript, sqrt_pst::Polynomial, }; +use ark_std::time::Instant; use ark_std::marker::PhantomData; use serde::Serialize; type F = ark_bls12_377::Fr; @@ -12,11 +13,15 @@ use ark_relations::r1cs::ConstraintSystem; use ark_ec::bls12::Bls12; use ark_ec::pairing::Pairing; use ark_relations::r1cs::ConstraintSynthesizer; - +use ark_std::rand::SeedableRng; +use ark_groth16::Groth16; +use ark_snark::SNARK; +use rand::rngs::OsRng; #[derive(Default, Clone, Serialize)] struct BenchmarkResults { power: usize, num_constraints: usize, + proving_time: u128, } fn main() { let params = get_bls12377_fq_params(); @@ -62,11 +67,27 @@ fn main() { _iv: PhantomData, }; let cs = ConstraintSystem::< as Pairing>::BaseField>::new_ref(); - circuit.generate_constraints(cs.clone()).unwrap(); - assert!(cs.is_satisfied().unwrap()); + circuit.clone().generate_constraints(cs.clone()).unwrap(); + // assert!(cs.is_satisfied().unwrap()); br.num_constraints = cs.num_constraints(); + let mut rng2 = rand_chacha::ChaChaRng::seed_from_u64(1776); + let (pk, vk) = Groth16::::circuit_specific_setup(circuit.clone(), &mut rng2).unwrap(); + + + let start = Instant::now(); + + let proof = Groth16::::prove(&pk, circuit.clone(), &mut OsRng).unwrap(); + + let duration = start.elapsed().as_millis(); + + br.proving_time = duration; + + + let ok = Groth16::::verify(&pk.vk, &[], &proof).unwrap(); + assert!(ok); + writer .serialize(br) .expect("unable to write results to csv");