diff --git a/eigentrust-zk/src/circuits/mod.rs b/eigentrust-zk/src/circuits/mod.rs index 032dc1da..f3d3a02e 100644 --- a/eigentrust-zk/src/circuits/mod.rs +++ b/eigentrust-zk/src/circuits/mod.rs @@ -153,5 +153,6 @@ pub type Threshold4 = ThresholdCircuit< Bn256_4_68, Bn254Params, SpongeHasher, + PoseidonNativeSponge, Params, >; diff --git a/eigentrust-zk/src/circuits/threshold/mod.rs b/eigentrust-zk/src/circuits/threshold/mod.rs index a7cc7d10..10b4a62b 100644 --- a/eigentrust-zk/src/circuits/threshold/mod.rs +++ b/eigentrust-zk/src/circuits/threshold/mod.rs @@ -57,6 +57,7 @@ pub struct ThresholdCircuit< P, EC, S, + H, R, > where E::Scalar: FieldExt, @@ -64,6 +65,7 @@ pub struct ThresholdCircuit< P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, EC: EccParams, S: SpongeHasherChipset, + H: SpongeHasher, R: RoundParams, { sets: Vec>, @@ -75,7 +77,7 @@ pub struct ThresholdCircuit< snarks: Vec>, as_proof: Option>, - _p: PhantomData<(P, EC, S, R)>, + _p: PhantomData<(P, EC, S, H, R)>, } impl< @@ -89,6 +91,7 @@ impl< P, EC, S, + H, R, > ThresholdCircuit< @@ -102,6 +105,7 @@ impl< P, EC, S, + H, R, > where E::Scalar: FieldExt, @@ -109,6 +113,7 @@ impl< P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, EC: EccParams, S: SpongeHasherChipset, + H: SpongeHasher, R: RoundParams, { /// Constructs a new ThresholdCircuit @@ -151,6 +156,7 @@ impl< P, EC, S, + H, R, > Circuit for ThresholdCircuit< @@ -164,6 +170,7 @@ impl< P, EC, S, + H, R, > where E::Scalar: FieldExt, @@ -171,6 +178,7 @@ impl< P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, EC: EccParams, S: SpongeHasherChipset, + H: SpongeHasher, R: RoundParams, { type Config = ThresholdCircuitConfig; @@ -400,7 +408,7 @@ impl< // verify if the "sets" & "scores" are valid, using aggregation verify // TODO: Use actual set and scores as PI for aggregator - let aggregator = AggregatorChipset::::new( + let aggregator = AggregatorChipset::::new( self.svk, self.snarks.clone(), self.as_proof.clone(), @@ -934,6 +942,7 @@ mod tests { P, EC, S, + PoseidonNativeSponge, R, > = ThresholdCircuit::new( &sets, &scores, &num_decomposed, &den_decomposed, svk, snarks, as_proof, @@ -1033,6 +1042,7 @@ mod tests { P, EC, S, + PoseidonNativeSponge, R, > = ThresholdCircuit::new::( &sets, &scores, &num_decomposed, &den_decomposed, svk, snarks, as_proof, diff --git a/eigentrust-zk/src/ecc/generic/mod.rs b/eigentrust-zk/src/ecc/generic/mod.rs index 90bd4e7a..3f43d4ca 100644 --- a/eigentrust-zk/src/ecc/generic/mod.rs +++ b/eigentrust-zk/src/ecc/generic/mod.rs @@ -811,13 +811,13 @@ where let selected_point = if self.bit.bit { let selected_x_integer = - AssignedInteger::new(self.p.x.integer.clone(), selected_x.map(|x| x.unwrap())); + AssignedInteger::new(self.p.x.integer, selected_x.map(|x| x.unwrap())); let selected_y_integer = AssignedInteger::new(self.p.y.integer, selected_y.map(|x| x.unwrap())); AssignedEcPoint::new(selected_x_integer, selected_y_integer) } else { let selected_x_integer = - AssignedInteger::new(self.q.x.integer.clone(), selected_x.map(|x| x.unwrap())); + AssignedInteger::new(self.q.x.integer, selected_x.map(|x| x.unwrap())); let selected_y_integer = AssignedInteger::new(self.q.y.integer, selected_y.map(|x| x.unwrap())); AssignedEcPoint::new(selected_x_integer, selected_y_integer) diff --git a/eigentrust-zk/src/ecc/same_curve/mod.rs b/eigentrust-zk/src/ecc/same_curve/mod.rs index ace1e134..1f1f9b85 100644 --- a/eigentrust-zk/src/ecc/same_curve/mod.rs +++ b/eigentrust-zk/src/ecc/same_curve/mod.rs @@ -16,7 +16,7 @@ use crate::{ IntegerEqualChipset, IntegerMulChip, IntegerReduceChip, IntegerSubChip, UnassignedInteger, }, params::{ecc::EccParams, rns::RnsParams}, - utils::{assigned_as_bool, be_assigned_bits_to_usize}, + utils::{be_assigned_bits_to_usize, to_bits}, Chip, Chipset, CommonConfig, FieldExt, UnassignedValue, }; use halo2::halo2curves::ff::PrimeField; @@ -672,7 +672,7 @@ where C::Scalar: FieldExt, { // Assigned bit - bit: AssignedCell, + bit: (bool, AssignedCell), // Assigned point p p: AssignedEcPoint, // Assigned point q @@ -688,7 +688,8 @@ where { /// Creates a new ecc table select chipset. pub fn new( - bit: AssignedCell, p: AssignedEcPoint, + bit: (bool, AssignedCell), + p: AssignedEcPoint, q: AssignedEcPoint, ) -> Self { Self { bit, p, q } @@ -716,7 +717,7 @@ where for i in 0..NUM_LIMBS { // Select x coordinate limbs let select = SelectChipset::new( - self.bit.clone(), + self.bit.1.clone(), self.p.x.limbs[i].clone(), self.q.x.limbs[i].clone(), ); @@ -725,7 +726,7 @@ where // Select y coordinate limbs let select = SelectChipset::new( - self.bit.clone(), + self.bit.1.clone(), self.p.y.limbs[i].clone(), self.q.y.limbs[i].clone(), ); @@ -733,15 +734,15 @@ where Some(select.synthesize(common, &config.main, layouter.namespace(|| "acc_y"))?); } - let selected_point = if assigned_as_bool::(self.bit) { + let selected_point = if self.bit.0 { let selected_x_integer = - AssignedInteger::new(self.p.x.integer.clone(), selected_x.map(|x| x.unwrap())); + AssignedInteger::new(self.p.x.integer, selected_x.map(|x| x.unwrap())); let selected_y_integer = AssignedInteger::new(self.p.y.integer, selected_y.map(|x| x.unwrap())); AssignedEcPoint::new(selected_x_integer, selected_y_integer) } else { let selected_x_integer = - AssignedInteger::new(self.q.x.integer.clone(), selected_x.map(|x| x.unwrap())); + AssignedInteger::new(self.q.x.integer, selected_x.map(|x| x.unwrap())); let selected_y_integer = AssignedInteger::new(self.q.y.integer, selected_y.map(|x| x.unwrap())); AssignedEcPoint::new(selected_x_integer, selected_y_integer) @@ -762,7 +763,7 @@ where // Assigned point p p: AssignedEcPoint, // Assigned scalar value - scalar: AssignedCell, + scalar: (C::Scalar, AssignedCell), // Aux points (to_add + to_sub) aux: AssignedAux, } @@ -777,7 +778,8 @@ where { /// Creates a new ecc mul chipset. pub fn new( - p: AssignedEcPoint, scalar: AssignedCell, + p: AssignedEcPoint, + scalar: (C::Scalar, AssignedCell), aux: AssignedAux, ) -> Self { assert!(aux.init.len() == 1); @@ -810,12 +812,19 @@ where &config.add, layouter.namespace(|| "aux_init_plus_scalar"), )?; - let bits = Bits2NumChip::new(self.scalar); + let bits = Bits2NumChip::new(self.scalar.1.clone()); let mut bits = bits.synthesize(common, &config.bits2num, layouter.namespace(|| "bits"))?; bits.reverse(); + let native_bits = { + let bits = to_bits(self.scalar.0.to_repr().as_ref()); + let mut native_bits = bits[..C::Scalar::NUM_BITS as usize].to_vec(); + native_bits.reverse(); + native_bits + }; + let acc_point_chip = EccTableSelectChipset::new( - bits[0].clone(), + (native_bits[0], bits[0].clone()), aux_init_plus_scalar.clone(), self.aux.init[0].clone(), ); @@ -826,7 +835,7 @@ where )?; let carry_point_chip = EccTableSelectChipset::new( - bits[1].clone(), + (native_bits[1], bits[1].clone()), aux_init_plus_scalar.clone(), self.aux.init[0].clone(), ); @@ -848,9 +857,9 @@ where acc_point = acc_add_chip.synthesize(common, &config.add, layouter.namespace(|| "acc_add"))?; - for bit in bits.iter().skip(2) { + for i in 2..bits.len() { let carry_point_chip = EccTableSelectChipset::new( - bit.clone(), + (native_bits[i], bits[i].clone()), aux_init_plus_scalar.clone(), self.aux.init[0].clone(), ); @@ -1233,7 +1242,7 @@ mod test { arithmetic::Field, circuit::{Layouter, Region, SimpleFloorPlanner, Value}, dev::MockProver, - halo2curves::bn256::{Fq, Fr, G1Affine}, + halo2curves::bn256::{Bn256, Fq, Fr, G1Affine}, plonk::{Circuit, ConstraintSystem, Error}, }; use num_bigint::BigUint; @@ -1544,12 +1553,12 @@ mod test { #[derive(Clone)] struct EccMulTestCircuit { p: UnassignedEcPoint, - value: Value, + value: (N, Value), } impl EccMulTestCircuit { fn new(p: EcPoint, value: N) -> Self { - Self { p: UnassignedEcPoint::from(p), value: Value::known(value) } + Self { p: UnassignedEcPoint::from(p), value: (value, Value::known(value)) } } } @@ -1558,7 +1567,10 @@ mod test { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self { p: UnassignedEcPoint::without_witnesses(&self.p), value: Value::unknown() } + Self { + p: UnassignedEcPoint::without_witnesses(&self.p), + value: (self.value.0.clone(), Value::unknown()), + } } fn configure(meta: &mut ConstraintSystem) -> TestConfig { @@ -1572,7 +1584,7 @@ mod test { || "scalar_mul_values", |region: Region<'_, N>| { let mut ctx = RegionCtx::new(region, 0); - let value = ctx.assign_advice(config.common.advice[0], self.value)?; + let value = ctx.assign_advice(config.common.advice[0], self.value.1)?; Ok(value) }, )?; @@ -1588,7 +1600,8 @@ mod test { let p_assigned = p_assigner.synthesize(&config.common, &(), layouter.namespace(|| "p assigner"))?; - let chip = EccMulChipset::new(p_assigned, value_assigned, auxes); + let chip = + EccMulChipset::new(p_assigned, (self.value.0.clone(), value_assigned), auxes); let result = chip.synthesize( &config.common, &config.ecc_mul, @@ -1632,6 +1645,33 @@ mod test { assert_eq!(prover.verify(), Ok(())); } + #[test] + fn should_mul_scalar_ecc_prod() { + // Testing ecc mul. + let rng = &mut thread_rng(); + let scalar = Fr::random(rng); + + let a_big = BigUint::from_str("2342876324689764345467879012938433459867545345").unwrap(); + let b_big = BigUint::from_str("6546457298123794342352534089237495253453455675").unwrap(); + let a = Integer::::new(a_big); + let b = Integer::::new(b_big); + let p_point = EcPoint::::new(a, b); + + let res = p_point.mul_scalar(scalar); + let test_chip = EccMulTestCircuit::new(p_point, scalar); + + let k = 14; + let mut p_ins = Vec::new(); + p_ins.extend(res.x.limbs); + p_ins.extend(res.y.limbs); + + let rng = &mut thread_rng(); + let params = crate::utils::generate_params(k); + let res = crate::utils::prove_and_verify::(params, test_chip, &[&p_ins], rng) + .unwrap(); + assert!(res); + } + #[derive(Clone)] struct EccBatchedMulTestCircuit { points: Vec>, diff --git a/eigentrust-zk/src/ecdsa/mod.rs b/eigentrust-zk/src/ecdsa/mod.rs index 0c1441be..d21eb467 100644 --- a/eigentrust-zk/src/ecdsa/mod.rs +++ b/eigentrust-zk/src/ecdsa/mod.rs @@ -452,8 +452,7 @@ where let x_candidate = r_point.x; - let new_x_int = Integer::from_limbs(x_candidate.integer.limbs); - let new_x = AssignedInteger::new(new_x_int, x_candidate.limbs); + let new_x = AssignedInteger::new(x_candidate.integer, x_candidate.limbs); let reducer = IntegerReduceChip::new(new_x); let reduced_x = reducer.synthesize( common, @@ -461,7 +460,12 @@ where layouter.namespace(|| "reduce base in scalar"), )?; - let ecc_eq_chipset = IntegerEqualChipset::new(reduced_x, self.signature.r); + let new_r: Integer = + Integer::new(self.signature.r.integer.value()); + let sig_r = ConstIntegerAssigner::new(new_r); + let sig_r = sig_r.synthesize(common, &(), layouter.namespace(|| "r"))?; + + let ecc_eq_chipset = IntegerEqualChipset::new(reduced_x, sig_r); let is_eq = ecc_eq_chipset.synthesize( common, &config.int_eq, diff --git a/eigentrust-zk/src/gadgets/bits2integer.rs b/eigentrust-zk/src/gadgets/bits2integer.rs index d7abf13a..998022bf 100644 --- a/eigentrust-zk/src/gadgets/bits2integer.rs +++ b/eigentrust-zk/src/gadgets/bits2integer.rs @@ -156,7 +156,7 @@ mod test { }, )?; - let assigned_integer = AssignedInteger::new( + let assigned_integer = AssignedInteger::::new( self.unassigned_integer.integer.clone(), assigned_limbs.map(|x| x.unwrap()), ); diff --git a/eigentrust-zk/src/gadgets/bits2num.rs b/eigentrust-zk/src/gadgets/bits2num.rs index eb49076a..7484fc71 100644 --- a/eigentrust-zk/src/gadgets/bits2num.rs +++ b/eigentrust-zk/src/gadgets/bits2num.rs @@ -21,15 +21,20 @@ impl Bits2NumChip { /// Create a new chip. pub fn new_exact(value: AssignedCell) -> Self { let fe = assigned_to_field(value.clone()); - let bits = field_to_bits::<_, B>(fe); - let bit_vals = bits.map(|x| Value::known(x)).to_vec(); + let bit_vals = match fe { + Some(fe) => field_to_bits::<_, B>(fe).map(|x| Value::known(x)).to_vec(), + None => field_to_bits::<_, B>(F::ZERO).map(|_| Value::unknown()).to_vec(), + }; Self { value, bits: bit_vals } } /// Create a new chip. pub fn new(value: AssignedCell) -> Self { let fe = assigned_to_field(value.clone()); - let bit_vals = field_to_bits_vec(fe).iter().map(|&x| Value::known(x)).collect(); + let bit_vals = match fe { + Some(fe) => field_to_bits_vec(fe).iter().map(|&x| Value::known(x)).collect(), + None => field_to_bits_vec(F::ZERO).iter().map(|_| Value::unknown()).collect(), + }; Self { value, bits: bit_vals } } } diff --git a/eigentrust-zk/src/integer/mod.rs b/eigentrust-zk/src/integer/mod.rs index 312ffd1f..02e5e658 100644 --- a/eigentrust-zk/src/integer/mod.rs +++ b/eigentrust-zk/src/integer/mod.rs @@ -7,7 +7,8 @@ use crate::{ main::{IsEqualChipset, MainConfig, SubChipset}, set::{SetChipset, SetConfig}, }, - params::rns::RnsParams, + params::rns::{compose_big_val, RnsParams}, + utils::fe_to_big_val, Chip, Chipset, CommonConfig, FieldExt, RegionCtx, UnassignedValue, }; use halo2::{ @@ -15,9 +16,64 @@ use halo2::{ plonk::{ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; -use native::{Quotient, ReductionWitness}; +use num_bigint::BigUint; use std::marker::PhantomData; +/// Enum for the two different type of Quotient. +#[derive(Clone, Debug)] +pub enum QuotientVal +where + P: RnsParams, +{ + /// Quotient type for the addition and subtraction. + Short(Value), + /// Quotient type for the multiplication and division. + Long(UnassignedInteger), +} + +impl + QuotientVal +where + P: RnsParams, +{ + /// Returns Quotient type for the addition or the subtraction. + pub fn short(self) -> Option> { + match self { + QuotientVal::Short(res) => Some(res), + _ => None, + } + } + + /// Returns Quotient type for the multiplication or the division. + pub fn long(self) -> Option> { + match self { + QuotientVal::Long(res) => Some(res), + _ => None, + } + } +} + +/// Structure for the ReductionWitness. +#[derive(Debug, Clone)] +pub struct ReductionWitnessVal< + W: FieldExt, + N: FieldExt, + const NUM_LIMBS: usize, + const NUM_BITS: usize, + P, +> where + P: RnsParams, +{ + /// Result from the operation. + pub(crate) result: UnassignedInteger, + /// Quotient from the operation. + pub(crate) quotient: QuotientVal, + /// Intermediate values from the operation. + pub(crate) intermediate: [Value; NUM_LIMBS], + /// Residue values from the operation. + pub(crate) residues: Vec>, +} + /// UnassignedInteger struct #[derive(Clone, Debug)] pub struct UnassignedInteger< @@ -59,7 +115,7 @@ where { fn from(int: Integer) -> Self { Self { - integer: Integer::::from_limbs(int.limbs), + integer: int.clone(), limbs: int.limbs.map(|x| Value::known(x)), _wrong_field: PhantomData, _rns: PhantomData, @@ -85,7 +141,7 @@ where /// Assigns given values and their reduction witnesses pub fn assign( x: &[AssignedCell; NUM_LIMBS], y_opt: Option<&[AssignedCell; NUM_LIMBS]>, - reduction_witness: &ReductionWitness, common: &CommonConfig, + reduction_witness: &ReductionWitnessVal, common: &CommonConfig, ctx: &mut RegionCtx, ) -> Result, Error> where @@ -103,7 +159,7 @@ where for i in 0..NUM_LIMBS { ctx.assign_advice( common.advice[i + 2 * NUM_LIMBS], - Value::known(reduction_witness.intermediate[i]), + reduction_witness.intermediate[i], )?; } @@ -113,7 +169,7 @@ where for i in 0..NUM_LIMBS { assigned_result[i] = Some(ctx.assign_advice( common.advice[i + 3 * NUM_LIMBS], - Value::known(reduction_witness.result.limbs[i]), + reduction_witness.result.limbs[i], )?); } @@ -121,25 +177,25 @@ where for i in 0..reduction_witness.residues.len() { ctx.assign_advice( common.advice[i + 4 * NUM_LIMBS], - Value::known(reduction_witness.residues[i]), + reduction_witness.residues[i], )?; } // Assign quotient match &reduction_witness.quotient { - Quotient::Short(n) => { - ctx.assign_advice(common.advice[5 * NUM_LIMBS - 1], Value::known(*n))?; + QuotientVal::Short(n) => { + ctx.assign_advice(common.advice[5 * NUM_LIMBS - 1], *n)?; }, - Quotient::Long(n) => { + QuotientVal::Long(n) => { ctx.next(); for i in 0..NUM_LIMBS { - ctx.assign_advice(common.advice[i], Value::known(n.limbs[i]))?; + ctx.assign_advice(common.advice[i], n.limbs[i])?; } }, } let assigned_result = AssignedInteger::new( - reduction_witness.result.clone(), + reduction_witness.result.integer.clone(), assigned_result.map(|x| x.unwrap()), ); Ok(assigned_result) @@ -236,7 +292,32 @@ where fn synthesize( self, common: &CommonConfig, selector: &Selector, mut layouter: impl Layouter, ) -> Result { - let reduction_witness = self.assigned_integer.integer.reduce(); + let native_reduction_witness = self.assigned_integer.integer.reduce(); + + let reduction_witness = { + let p_prime = P::negative_wrong_modulus_decomposed().map(Value::known); + let a = self.assigned_integer.value(); + let (q, res) = P::construct_reduce_qr_val(a); + + // Calculate the intermediate values for the ReductionWitness. + let mut t = [Value::known(N::ZERO); NUM_LIMBS]; + for i in 0..NUM_LIMBS { + t[i] = self.assigned_integer.limbs[i].value().cloned() + p_prime[i] * q; + } + + // Calculate the residue values for the ReductionWitness. + let residues = P::residues_val(&res, &t); + + // Construct correct type for the ReductionWitness + let result_int = UnassignedInteger::new(native_reduction_witness.result, res); + let quotient_n = QuotientVal::Short(q); + ReductionWitnessVal { + result: result_int, + quotient: quotient_n, + intermediate: t, + residues, + } + }; layouter.assign_region( || "reduce_operation", |region: Region<'_, N>| { @@ -350,7 +431,36 @@ where fn synthesize( self, common: &CommonConfig, selector: &Selector, mut layouter: impl Layouter, ) -> Result { - let reduction_witness = self.x.integer.add(&self.y.integer); + let native_reduction_witness = self.x.integer.add(&self.y.integer); + + let reduction_witness = { + let p_prime = P::negative_wrong_modulus_decomposed().map(Value::known); + let a = self.x.value(); + let b = self.y.value(); + let (q, res) = P::construct_add_qr_val(a, b); + + // Calculate the intermediate values for the ReductionWitness. + let mut t = [Value::known(N::ZERO); NUM_LIMBS]; + for i in 0..NUM_LIMBS { + t[i] = self.x.limbs[i].value().cloned() + + self.y.limbs[i].value().cloned() + + p_prime[i] * q; + } + + // Calculate the residue values for the ReductionWitness. + let residues = P::residues_val(&res, &t); + + // Construct correct type for the ReductionWitness + let result_int = UnassignedInteger::new(native_reduction_witness.result, res); + let quotient_n = QuotientVal::Short(q); + ReductionWitnessVal { + result: result_int, + quotient: quotient_n, + intermediate: t, + residues, + } + }; + layouter.assign_region( || "add_operation", |region: Region<'_, N>| { @@ -467,7 +577,36 @@ where fn synthesize( self, common: &CommonConfig, selector: &Selector, mut layouter: impl Layouter, ) -> Result { - let reduction_witness = self.x.integer.sub(&self.y.integer); + let native_reduction_witness = self.x.integer.sub(&self.y.integer); + + let reduction_witness = { + let p_prime = P::negative_wrong_modulus_decomposed().map(Value::known); + let a = self.x.value(); + let b = self.y.value(); + let (q, res) = P::construct_sub_qr_val(a, b); + + // Calculate the intermediate values for the ReductionWitness. + let mut t = [Value::known(N::ZERO); NUM_LIMBS]; + for i in 0..NUM_LIMBS { + t[i] = self.x.limbs[i].value().cloned() - self.y.limbs[i].value().cloned() + + p_prime[i] * q; + } + + // Calculate the residue values for the ReductionWitness. + let residues = P::residues_val(&res, &t); + + // Construct correct type for the ReductionWitness + let result_int = UnassignedInteger::new(native_reduction_witness.result, res); + let quotient_n = QuotientVal::Short(q); + + ReductionWitnessVal { + result: result_int, + quotient: quotient_n, + intermediate: t, + residues, + } + }; + layouter.assign_region( || "sub_operation", |region: Region<'_, N>| { @@ -587,7 +726,42 @@ where fn synthesize( self, common: &CommonConfig, selector: &Selector, mut layouter: impl Layouter, ) -> Result { - let reduction_witness = self.x.integer.mul(&self.y.integer); + let native_reduction_witness = self.x.integer.mul(&self.y.integer); + + let reduction_witness = { + let p_prime = P::negative_wrong_modulus_decomposed().map(Value::known); + let a = self.x.value(); + let b = self.y.value(); + let (q, res) = P::construct_mul_qr_val(a, b); + + // Calculate the intermediate values for the ReductionWitness. + let mut t = [Value::known(N::ZERO); NUM_LIMBS]; + for k in 0..NUM_LIMBS { + for i in 0..=k { + let j = k - i; + t[i + j] = t[i + j] + + self.x.limbs[i].value().cloned() * self.y.limbs[j].value().cloned() + + p_prime[i] * q[j]; + } + } + + // Calculate the residue values for the ReductionWitness. + let residues = P::residues_val(&res, &t); + + // Construct correct type for the ReductionWitness. + let result_int = UnassignedInteger::new(native_reduction_witness.result, res); + let quotient_int = QuotientVal::Long(UnassignedInteger::new( + native_reduction_witness.quotient.long().unwrap(), + q, + )); + ReductionWitnessVal { + result: result_int, + quotient: quotient_int, + intermediate: t, + residues, + } + }; + layouter.assign_region( || "mul_operation", |region: Region<'_, N>| { @@ -707,7 +881,42 @@ where fn synthesize( self, common: &CommonConfig, selector: &Selector, mut layouter: impl Layouter, ) -> Result { - let reduction_witness = self.x.integer.div(&self.y.integer); + let native_reduction_witness = self.x.integer.div(&self.y.integer); + + let reduction_witness = { + let p_prime = P::negative_wrong_modulus_decomposed().map(Value::known); + let a = self.x.value(); + let b = self.y.value(); + let (q, res) = P::construct_div_qr_val(a, b); + + // Calculate the intermediate values for the ReductionWitness. + let mut t = [Value::known(N::ZERO); NUM_LIMBS]; + for k in 0..NUM_LIMBS { + for i in 0..=k { + let j = k - i; + t[i + j] = + t[i + j] + res[i] * self.y.limbs[j].value().cloned() + p_prime[i] * q[j]; + } + } + + // Calculate the residue values for the ReductionWitness. + let residues = P::residues_val(&res, &t); + + // Construct correct type for the ReductionWitness. + let result_int = UnassignedInteger::new(native_reduction_witness.result, res); + let quotient_int = QuotientVal::Long(UnassignedInteger::new( + native_reduction_witness.quotient.long().unwrap(), + q, + )); + + ReductionWitnessVal { + result: result_int, + quotient: quotient_int, + intermediate: t, + residues, + } + }; + layouter.assign_region( || "div_operation", |region: Region<'_, N>| { @@ -822,6 +1031,8 @@ pub struct AssignedInteger< pub(crate) integer: Integer, // Limbs of the assigned integer. pub(crate) limbs: [AssignedCell; NUM_LIMBS], + + _p: PhantomData<(W, P)>, } impl @@ -833,7 +1044,13 @@ where pub fn new( integer: Integer, limbs: [AssignedCell; NUM_LIMBS], ) -> Self { - Self { integer, limbs } + Self { integer, limbs, _p: PhantomData } + } + + /// Retuns a value of AssignedInteger + pub fn value(&self) -> Value { + let limb_values = self.limbs.clone().map(|limb| fe_to_big_val(limb.value().cloned())); + compose_big_val::(limb_values) } } @@ -1068,8 +1285,7 @@ mod test { }, )?; - let x = - AssignedInteger::new(self.x.integer.clone(), x_limbs_assigned.map(|x| x.unwrap())); + let x = AssignedInteger::new(self.x.integer, x_limbs_assigned.map(|x| x.unwrap())); Ok(x) } } @@ -1120,10 +1336,8 @@ mod test { }, )?; - let x = - AssignedInteger::new(self.x.integer.clone(), x_limbs_assigned.map(|x| x.unwrap())); - let y = - AssignedInteger::new(self.y.integer.clone(), y_limbs_assigned.map(|x| x.unwrap())); + let x = AssignedInteger::new(self.x.integer, x_limbs_assigned.map(|x| x.unwrap())); + let y = AssignedInteger::new(self.y.integer, y_limbs_assigned.map(|x| x.unwrap())); Ok((x, y)) } } diff --git a/eigentrust-zk/src/params/rns/mod.rs b/eigentrust-zk/src/params/rns/mod.rs index d58a88f7..ce1f37a8 100644 --- a/eigentrust-zk/src/params/rns/mod.rs +++ b/eigentrust-zk/src/params/rns/mod.rs @@ -4,6 +4,7 @@ use crate::{ FieldExt, }; use halo2::{ + circuit::Value, halo2curves::{bn256::Fr, group::ff::PrimeField}, plonk::Expression, }; @@ -56,6 +57,24 @@ pub trait RnsParams; NUM_LIMBS], t: &[Value; NUM_LIMBS]) -> Vec> { + let lsh1 = Value::known(Self::left_shifters()[1]); + let rsh2 = Value::known(Self::right_shifters()[2]); + + let mut res = Vec::new(); + let mut carry = Value::known(N::ZERO); + for i in (0..NUM_LIMBS).step_by(2) { + let (t_0, t_1) = (t[i], t[i + 1]); + let (r_0, r_1) = (n[i], n[i + 1]); + let u = t_0 + (t_1 * lsh1) - r_0 - (lsh1 * r_1) + carry; + let v = u * rsh2; + carry = v; + res.push(v) + } + res + } + /// Returns `quotient` and `remainder` for the reduce operation. fn construct_reduce_qr(a_bn: BigUint) -> (N, [N; NUM_LIMBS]) { let wrong_mod_bn = Self::wrong_modulus(); @@ -65,6 +84,12 @@ pub trait RnsParams) -> (Value, [Value; NUM_LIMBS]) { + let (q, result) = a_bn.map(|a_bn| Self::construct_reduce_qr(a_bn)).unzip(); + (q, result.transpose_array()) + } + /// Returns `quotient` and `remainder` for the add operation. fn construct_add_qr(a_bn: BigUint, b_bn: BigUint) -> (N, [N; NUM_LIMBS]) { let wrong_mod_bn = Self::wrong_modulus(); @@ -77,6 +102,15 @@ pub trait RnsParams, b_bn: Value, + ) -> (Value, [Value; NUM_LIMBS]) { + let (q, result) = + a_bn.zip(b_bn).map(|(a_bn, b_bn)| Self::construct_add_qr(a_bn, b_bn)).unzip(); + (q, result.transpose_array()) + } + /// Returns `quotient` and `remainder` for the sub operation. fn construct_sub_qr(a_bn: BigUint, b_bn: BigUint) -> (N, [N; NUM_LIMBS]) { let wrong_mod_bn = Self::wrong_modulus(); @@ -97,6 +131,15 @@ pub trait RnsParams, b_bn: Value, + ) -> (Value, [Value; NUM_LIMBS]) { + let (q, result) = + a_bn.zip(b_bn).map(|(a_bn, b_bn)| Self::construct_sub_qr(a_bn, b_bn)).unzip(); + (q, result.transpose_array()) + } + /// Returns `quotient` and `remainder` for the mul operation. fn construct_mul_qr(a_bn: BigUint, b_bn: BigUint) -> ([N; NUM_LIMBS], [N; NUM_LIMBS]) { let wrong_mod_bn = Self::wrong_modulus(); @@ -106,6 +149,15 @@ pub trait RnsParams, b_bn: Value, + ) -> ([Value; NUM_LIMBS], [Value; NUM_LIMBS]) { + let (q, result) = + a_bn.zip(b_bn).map(|(a_bn, b_bn)| Self::construct_mul_qr(a_bn, b_bn)).unzip(); + (q.transpose_array(), result.transpose_array()) + } + /// Returns `quotient` and `remainder` for the div operation. fn construct_div_qr(a_bn: BigUint, b_bn: BigUint) -> ([N; NUM_LIMBS], [N; NUM_LIMBS]) { let b_invert = Self::invert(b_bn.clone()).unwrap().value(); @@ -120,6 +172,15 @@ pub trait RnsParams, b_bn: Value, + ) -> ([Value; NUM_LIMBS], [Value; NUM_LIMBS]) { + let (q, result) = + a_bn.zip(b_bn).map(|(a_bn, b_bn)| Self::construct_div_qr(a_bn, b_bn)).unzip(); + (q.transpose_array(), result.transpose_array()) + } + /// Constraint for the binary part of `Chinese Remainder Theorem`. fn constrain_binary_crt(t: [N; NUM_LIMBS], result: [N; NUM_LIMBS], residues: Vec) -> bool { let lsh_one = Self::left_shifters()[1]; @@ -250,3 +311,14 @@ pub fn compose_big( } res } + +/// Returns [`BigUint`] by composing `limbs`. +pub fn compose_big_val( + input: [Value; NUM_LIMBS], +) -> Value { + let mut res = Value::known(BigUint::zero()); + for i in (0..NUM_LIMBS).rev() { + res = (res.map(|res| res << NUM_BITS)) + input[i].clone(); + } + res +} diff --git a/eigentrust-zk/src/utils.rs b/eigentrust-zk/src/utils.rs index a9137df9..29c81c0c 100644 --- a/eigentrust-zk/src/utils.rs +++ b/eigentrust-zk/src/utils.rs @@ -80,11 +80,11 @@ pub fn assigned_as_bool(bit: AssignedCell) -> bool { } /// Returns field value from the assigned cell value -pub fn assigned_to_field(cell: AssignedCell) -> F { +pub fn assigned_to_field(cell: AssignedCell) -> Option { let cell_value = cell.value(); - let mut arr = F::ZERO; + let mut arr = None; cell_value.map(|f| { - arr = *f; + arr = Some(*f); }); arr } @@ -328,6 +328,11 @@ pub fn fe_to_big(fe: F) -> BigUint { BigUint::from_bytes_le(fe.to_repr().as_ref()) } +/// Returns [`BigUint`] representation for the given [`FieldExt`]. +pub fn fe_to_big_val(fe: Value) -> Value { + fe.map(|fe| fe_to_big(fe)) +} + /// Converts a `BigRational` into scaled, decomposed numerator and denominator arrays of field elements. pub fn big_to_fe_rat( ratio: BigRational, diff --git a/eigentrust-zk/src/verifier/aggregator/mod.rs b/eigentrust-zk/src/verifier/aggregator/mod.rs index 9511698a..cdf12d70 100644 --- a/eigentrust-zk/src/verifier/aggregator/mod.rs +++ b/eigentrust-zk/src/verifier/aggregator/mod.rs @@ -44,7 +44,7 @@ where E::Scalar: FieldExt, { protocol: PlonkProtocol, - instances: Vec>>, + instances: (Vec>, Vec>>), proof: Option>, } @@ -61,11 +61,14 @@ where fn from(snark: Snark) -> Self { Self { protocol: snark.protocol, - instances: snark - .instances - .into_iter() - .map(|instances| instances.into_iter().map(Value::known).collect_vec()) - .collect(), + instances: ( + snark.instances.clone(), + snark + .instances + .into_iter() + .map(|instances| instances.into_iter().map(Value::known).collect_vec()) + .collect(), + ), proof: Some(snark.proof), } } @@ -80,11 +83,7 @@ where pub fn without_witness(&self) -> Self { UnassignedSnark { protocol: self.protocol.clone(), - instances: self - .instances - .iter() - .map(|instances| vec![Value::unknown(); instances.len()]) - .collect(), + instances: self.instances.clone(), proof: None, } } @@ -96,11 +95,12 @@ where #[derive(Debug)] /// AggregatorChipset -pub struct AggregatorChipset +pub struct AggregatorChipset where E: MultiMillerLoop, P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, ::Base: FieldExt, E::Scalar: FieldExt, @@ -112,15 +112,16 @@ where // Accumulation Scheme Proof as_proof: Option>, // Phantom Data - _p: PhantomData<(P, S, EC, E)>, + _p: PhantomData<(P, S, H, EC, E)>, } -impl - AggregatorChipset +impl + AggregatorChipset where E: MultiMillerLoop, P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, ::Base: FieldExt, E::Scalar: FieldExt, @@ -133,12 +134,13 @@ where } } -impl Clone - for AggregatorChipset +impl Clone + for AggregatorChipset where E: MultiMillerLoop, P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, ::Base: FieldExt, E::Scalar: FieldExt, @@ -181,12 +183,13 @@ where } } -impl Chipset - for AggregatorChipset +impl Chipset + for AggregatorChipset where E: MultiMillerLoop, P: RnsParams<::Base, E::Scalar, NUM_LIMBS, NUM_BITS>, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, ::Base: FieldExt, E::Scalar: FieldExt, @@ -207,7 +210,7 @@ where let mut assigned_instances = Vec::new(); for snark in &self.snarks { let mut instances_collector = Vec::new(); - for inst_vec in &snark.instances { + for inst_vec in &snark.instances.1 { let mut inst_vec_collector = Vec::new(); for inst in inst_vec { let value = ctx.assign_advice(common.advice[advice_i], *inst)?; @@ -242,11 +245,13 @@ where let mut accumulators = Vec::new(); for (i, snark) in self.snarks.iter().enumerate() { let mut loaded_instances = Vec::new(); - for inst_vec in &assigned_instances[i] { + for (j, inst_vec) in assigned_instances[i].iter().enumerate() { let mut loaded_inst_vec = Vec::new(); - for inst in inst_vec { - let loaded_instance = - Halo2LScalar::new(inst.clone(), loader_config.clone()); + for (k, inst) in inst_vec.iter().enumerate() { + let loaded_instance = Halo2LScalar::new( + (snark.instances.0[j][k], inst.clone()), + loader_config.clone(), + ); loaded_inst_vec.push(loaded_instance); } loaded_instances.push(loaded_inst_vec); @@ -262,6 +267,7 @@ where NUM_BITS, P, S, + H, EC, > = TranscriptReadChipset::new(snark.proof(), loader_config.clone()); @@ -286,6 +292,7 @@ where NUM_BITS, P, S, + H, EC, > = TranscriptReadChipset::new(as_proof, loader_config); let proof = @@ -641,12 +648,15 @@ mod test { fn synthesize( &self, config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let aggregator_chipset = - AggregatorChipset::::new( - self.svk, - self.snarks.clone(), - self.as_proof.clone(), - ); + let aggregator_chipset = AggregatorChipset::< + E, + NUM_LIMBS, + NUM_BITS, + P, + SpongeHasher, + PoseidonNativeSponge, + EC, + >::new(self.svk, self.snarks.clone(), self.as_proof.clone()); let accumulator_limbs = aggregator_chipset.synthesize( &config.common, &config.aggregator, @@ -665,7 +675,7 @@ mod test { fn test_aggregator() { // Testing Aggregator let rng = &mut thread_rng(); - let k = 22; + let k = 21; let params = generate_params::(k); let random_circuit_1 = MulChip::new(Scalar::one(), Scalar::one()); @@ -687,6 +697,35 @@ mod test { assert_eq!(prover.verify(), Ok(())); } + #[ignore = "Aggregator takes too long to run"] + #[test] + fn test_aggregator_prod() { + // Testing Aggregator + let rng = &mut thread_rng(); + let k = 21; + let params = generate_params::(k); + + let random_circuit_1 = MulChip::new(Scalar::one(), Scalar::one()); + let random_circuit_2 = MulChip::new(Scalar::one(), Scalar::one()); + + let instances_1: Vec> = vec![vec![Scalar::one()]]; + let instances_2: Vec> = vec![vec![Scalar::one()]]; + + let snark_1 = Snark::new(¶ms, random_circuit_1, instances_1, rng); + let snark_2 = Snark::new(¶ms, random_circuit_2, instances_2, rng); + + let snarks = vec![snark_1, snark_2]; + let NativeAggregator { svk, snarks, instances, as_proof, .. } = + NativeAggregator::new(¶ms, snarks); + + let aggregator_circuit = AggregatorTestCircuit::new(svk, snarks, as_proof); + + let params = generate_params(k); + let res = prove_and_verify::(params, aggregator_circuit, &[&instances], rng) + .unwrap(); + assert!(res); + } + #[ignore = "Et Aggregator takes too long to run"] #[test] fn test_et_aggregator_prod() { diff --git a/eigentrust-zk/src/verifier/loader/mod.rs b/eigentrust-zk/src/verifier/loader/mod.rs index 958a7c80..d69a977c 100644 --- a/eigentrust-zk/src/verifier/loader/mod.rs +++ b/eigentrust-zk/src/verifier/loader/mod.rs @@ -4,9 +4,8 @@ use crate::{ AuxConfig, EccAddConfig, EccMulConfig, }, gadgets::main::{AddChipset, InverseChipset, MainConfig, MulChipset, SubChipset}, - integer::{native::Integer, AssignedInteger}, + integer::{native::Integer, AssignedInteger, UnassignedInteger}, params::{ecc::EccParams, rns::RnsParams}, - utils::assigned_to_field, Chipset, CommonConfig, FieldExt, RegionCtx, SpongeHasherChipset, }; use halo2::{ @@ -56,6 +55,10 @@ pub struct LoaderConfig< pub(crate) sponge: >::Config, // Aux_init and Aux_fin for the ecc_mul operation pub(crate) aux: AssignedAux, + + num_scalar: Rc>, + num_ec_point: Rc>, + // PhantomData _curve: PhantomData, _p: PhantomData

, @@ -90,6 +93,9 @@ where .unwrap(); let layouter_rc = Rc::new(RefCell::new(layouter)); + let num_scalar = Rc::new(RefCell::default()); + let num_ec_point = Rc::new(RefCell::default()); + Self { layouter: layouter_rc, common, @@ -98,6 +104,8 @@ where main, sponge, aux, + num_scalar, + num_ec_point, _curve: PhantomData, _p: PhantomData, } @@ -124,13 +132,15 @@ where /// Returns a copy of the value. fn clone(&self) -> Self { Self { - layouter: self.layouter.clone(), + layouter: Rc::clone(&self.layouter), common: self.common.clone(), ecc_mul_scalar: self.ecc_mul_scalar.clone(), ecc_add: self.ecc_add.clone(), main: self.main.clone(), sponge: self.sponge.clone(), aux: self.aux.clone(), + num_scalar: Rc::clone(&self.num_scalar), + num_ec_point: Rc::clone(&self.num_ec_point), _curve: PhantomData, _p: PhantomData, } @@ -178,9 +188,11 @@ pub struct Halo2LScalar< C::Scalar: FieldExt, { // Inner value for the halo2 loaded scalar - pub(crate) inner: AssignedCell, + pub(crate) inner: (C::Scalar, AssignedCell), // Loader pub(crate) loader: LoaderConfig<'a, C, L, NUM_LIMBS, NUM_BITS, P, S, EC>, + // index + index: usize, _h: PhantomData, } @@ -203,10 +215,12 @@ where { /// Creates a new Halo2LScalar pub fn new( - value: AssignedCell, + value: (C::Scalar, AssignedCell), loader: LoaderConfig<'a, C, L, NUM_LIMBS, NUM_BITS, P, S, EC>, ) -> Self { - Self { inner: value, loader, _h: PhantomData } + let index = *loader.num_scalar.borrow(); + *loader.num_scalar.borrow_mut() += 1; + Self { inner: value, index, loader, _h: PhantomData } } } @@ -229,7 +243,12 @@ where { /// Returns a copy of the value. fn clone(&self) -> Self { - Self { inner: self.inner.clone(), loader: self.loader.clone(), _h: PhantomData } + Self { + inner: self.inner.clone(), + loader: self.loader.clone(), + index: self.index, + _h: PhantomData, + } } } @@ -276,10 +295,7 @@ where /// This method tests for `self` and `other` values to be equal, and is /// used by `==`. fn eq(&self, other: &Self) -> bool { - let lhs = assigned_to_field(self.inner.clone()); - let rhs = assigned_to_field(other.inner.clone()); - - lhs == rhs + self.index == other.index } } @@ -303,13 +319,18 @@ where /// Returns multiplicative inversion if any. fn invert(&self) -> Option { let mut layouter_mut = self.loader.layouter.borrow_mut(); - let inv_chipset = InverseChipset::new(self.inner.clone()); + let inv_chipset = InverseChipset::new(self.inner.1.clone()); let inv_op = inv_chipset.synthesize( &self.loader.common, &self.loader.main, layouter_mut.namespace(|| "loader_inverse"), ); - inv_op.ok().map(|x| Self { inner: x, loader: self.loader.clone(), _h: PhantomData }) + inv_op.ok().map(|x| { + Halo2LScalar::new( + (FieldOps::invert(&self.inner.0).unwrap(), x), + self.loader.clone(), + ) + }) } } @@ -338,7 +359,7 @@ where /// Performs the `+` operation. fn add(self, rhs: &'a Self) -> Self { let mut layouter_mut = self.loader.layouter.borrow_mut(); - let add_chipset = AddChipset::new(self.inner, rhs.inner.clone()); + let add_chipset = AddChipset::new(self.inner.1.clone(), rhs.inner.1.clone()); let add = add_chipset .synthesize( &self.loader.common, @@ -346,7 +367,7 @@ where layouter_mut.namespace(|| "loader_add"), ) .unwrap(); - Self { inner: add, loader: self.loader.clone(), _h: PhantomData } + Halo2LScalar::new((self.inner.0.add(rhs.inner.0), add), self.loader.clone()) } } @@ -447,7 +468,7 @@ where /// Performs the `*` operation. fn mul(self, rhs: &'a Self) -> Self { let mut layouter_mut = self.loader.layouter.borrow_mut(); - let mul_chipset = MulChipset::new(self.inner, rhs.inner.clone()); + let mul_chipset = MulChipset::new(self.inner.1.clone(), rhs.inner.1.clone()); let mul = mul_chipset .synthesize( &self.loader.common, @@ -455,7 +476,7 @@ where layouter_mut.namespace(|| "loader_mul"), ) .unwrap(); - Self { inner: mul, loader: self.loader.clone(), _h: PhantomData } + Halo2LScalar::new((self.inner.0.mul(rhs.inner.0), mul), self.loader.clone()) } } @@ -556,7 +577,7 @@ where /// Performs the `-` operation. fn sub(self, rhs: &'a Self) -> Self { let mut layouter_mut = self.loader.layouter.borrow_mut(); - let sub_chipset = SubChipset::new(self.inner, rhs.inner.clone()); + let sub_chipset = SubChipset::new(self.inner.1.clone(), rhs.inner.1.clone()); let sub = sub_chipset .synthesize( &self.loader.common, @@ -564,7 +585,7 @@ where layouter_mut.namespace(|| "loader_sub"), ) .unwrap(); - Self { inner: sub, loader: self.loader.clone(), _h: PhantomData } + Halo2LScalar::new((self.inner.0.sub(rhs.inner.0), sub), self.loader.clone()) } } @@ -664,7 +685,7 @@ where /// Performs the unary `-` operation. fn neg(self) -> Self { let mut layouter_mut = self.loader.layouter.borrow_mut(); - let sub_chipset = SubChipset::new(self.inner.clone(), self.inner.clone()); + let sub_chipset = SubChipset::new(self.inner.1.clone(), self.inner.1.clone()); let zero = sub_chipset .synthesize( &self.loader.common, @@ -672,7 +693,7 @@ where layouter_mut.namespace(|| "loader_zero"), ) .unwrap(); - let sub_chipset = SubChipset::new(zero, self.inner); + let sub_chipset = SubChipset::new(zero, self.inner.1.clone()); let neg = sub_chipset .synthesize( &self.loader.common, @@ -680,7 +701,7 @@ where layouter_mut.namespace(|| "loader_neg"), ) .unwrap(); - Self { inner: neg, loader: self.loader.clone(), _h: PhantomData } + Halo2LScalar::new((-self.inner.0, neg), self.loader.clone()) } } @@ -741,7 +762,7 @@ where ) .unwrap(); - Halo2LScalar::new(assigned_value, self.clone()) + Halo2LScalar::new((*value, assigned_value), self.clone()) } /// Assert `lhs` and `rhs` field elements are equal. @@ -754,7 +775,7 @@ where || "assert_eq", |region: Region<'_, C::Scalar>| { let mut ctx = RegionCtx::new(region, 0); - ctx.constrain_equal(lhs.inner.clone(), rhs.inner.clone())?; + ctx.constrain_equal(lhs.inner.1.clone(), rhs.inner.1.clone())?; Ok(()) }, ) @@ -784,6 +805,8 @@ pub struct Halo2LEcPoint< pub(crate) inner: AssignedEcPoint, // Loader pub(crate) loader: LoaderConfig<'a, C, L, NUM_LIMBS, NUM_BITS, P, S, EC>, + // index + index: usize, _h: PhantomData, } @@ -809,7 +832,9 @@ where value: AssignedEcPoint, loader: LoaderConfig<'a, C, L, NUM_LIMBS, NUM_BITS, P, S, EC>, ) -> Self { - Self { inner: value, loader, _h: PhantomData } + let index = *loader.num_ec_point.borrow(); + *loader.num_ec_point.borrow_mut() += 1; + Self { inner: value, index, loader, _h: PhantomData } } } @@ -832,7 +857,12 @@ where { /// Returns a copy of the value. fn clone(&self) -> Self { - Self { inner: self.inner.clone(), loader: self.loader.clone(), _h: PhantomData } + Self { + inner: self.inner.clone(), + loader: self.loader.clone(), + index: self.index, + _h: PhantomData, + } } } @@ -879,8 +909,7 @@ where /// This method tests for `self` and `other` values to be equal, and is used /// by `==`. fn eq(&self, other: &Self) -> bool { - self.inner.x.integer == other.inner.x.integer - && self.inner.y.integer == other.inner.y.integer + self.index == other.index } } @@ -931,8 +960,10 @@ where /// Load a constant elliptic curve point. fn ec_point_load_const(&self, value: &C) -> Self::LoadedEcPoint { let coords: Coordinates = Option::from(value.coordinates()).unwrap(); - let x = Integer::from_w(*coords.x()); - let y = Integer::from_w(*coords.y()); + let x: UnassignedInteger = + UnassignedInteger::from(Integer::from_w(*coords.x())); + let y: UnassignedInteger = + UnassignedInteger::from(Integer::from_w(*coords.y())); let mut layouter = self.layouter.borrow_mut(); let (x_limbs, y_limbs) = layouter .assign_region( @@ -944,22 +975,20 @@ where let mut y_limbs: [Option>; NUM_LIMBS] = [(); NUM_LIMBS].map(|_| None); for i in 0..NUM_LIMBS { - x_limbs[i] = Some( - ctx.assign_from_constant(self.common.advice[i], x.limbs[i]).unwrap(), - ); + x_limbs[i] = + Some(ctx.assign_advice(self.common.advice[i], x.limbs[i]).unwrap()); } ctx.next(); for i in 0..NUM_LIMBS { - y_limbs[i] = Some( - ctx.assign_from_constant(self.common.advice[i], y.limbs[i]).unwrap(), - ); + y_limbs[i] = + Some(ctx.assign_advice(self.common.advice[i], y.limbs[i]).unwrap()); } Ok((x_limbs.map(|x| x.unwrap()), y_limbs.map(|x| x.unwrap()))) }, ) .unwrap(); - let x_assigned = AssignedInteger::new(x, x_limbs); - let y_assigned = AssignedInteger::new(y, y_limbs); + let x_assigned = AssignedInteger::new(x.integer, x_limbs); + let y_assigned = AssignedInteger::new(y.integer, y_limbs); let assigned_point = AssignedEcPoint::new(x_assigned, y_assigned); Halo2LEcPoint::new(assigned_point, self.clone()) @@ -1203,11 +1232,11 @@ mod test { ); let lscalar_x: Halo2LScalar = - Halo2LScalar::new(assigned_x, loader_config.clone()); + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); let inverted_lscalar_x = lscalar_x.invert().unwrap(); loader_config.layouter.borrow_mut().constrain_instance( - inverted_lscalar_x.inner.cell(), + inverted_lscalar_x.inner.1.cell(), config.common.instance, 0, )?; @@ -1284,13 +1313,15 @@ mod test { config.poseidon_sponge, ); - let lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); let lscalar_sum = lscalar_x + lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_sum.inner.cell(), + lscalar_sum.inner.1.cell(), config.common.instance, 0, )?; @@ -1368,13 +1399,15 @@ mod test { config.poseidon_sponge, ); - let mut lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let mut lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); lscalar_x += lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_x.inner.cell(), + lscalar_x.inner.1.cell(), config.common.instance, 0, )?; @@ -1454,13 +1487,15 @@ mod test { config.poseidon_sponge, ); - let lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); let lscalar_prod = lscalar_x * lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_prod.inner.cell(), + lscalar_prod.inner.1.cell(), config.common.instance, 0, )?; @@ -1538,13 +1573,15 @@ mod test { config.poseidon_sponge, ); - let mut lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let mut lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); lscalar_x *= lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_x.inner.cell(), + lscalar_x.inner.1.cell(), config.common.instance, 0, )?; @@ -1624,13 +1661,15 @@ mod test { config.poseidon_sponge, ); - let lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); let lscalar_sum = lscalar_x - lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_sum.inner.cell(), + lscalar_sum.inner.1.cell(), config.common.instance, 0, )?; @@ -1708,13 +1747,15 @@ mod test { config.poseidon_sponge, ); - let mut lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let mut lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); lscalar_x -= lscalar_y; loader_config.layouter.borrow_mut().constrain_instance( - lscalar_x.inner.cell(), + lscalar_x.inner.1.cell(), config.common.instance, 0, )?; @@ -1790,11 +1831,12 @@ mod test { config.poseidon_sponge, ); - let lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); + let lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); let neg_lscalar_x = -lscalar_x; loader_config.layouter.borrow_mut().constrain_instance( - neg_lscalar_x.inner.cell(), + neg_lscalar_x.inner.1.cell(), config.common.instance, 0, )?; @@ -1858,7 +1900,7 @@ mod test { let lscalar_one = loader_config.load_const(&Scalar::one()); loader_config.layouter.borrow_mut().constrain_instance( - lscalar_one.inner.cell(), + lscalar_one.inner.1.cell(), config.common.instance, 0, )?; @@ -1930,8 +1972,10 @@ mod test { config.poseidon_sponge, ); - let lscalar_x = Halo2LScalar::new(assigned_x, loader_config.clone()); - let lscalar_y = Halo2LScalar::new(assigned_y, loader_config.clone()); + let lscalar_x = + Halo2LScalar::new((self.x.inner.clone(), assigned_x), loader_config.clone()); + let lscalar_y = + Halo2LScalar::new((self.y.inner.clone(), assigned_y), loader_config.clone()); let res = loader_config .assert_eq("x == y", &lscalar_x, &lscalar_y) @@ -2236,11 +2280,12 @@ mod test { let mut halo2_pairs = Vec::new(); for (assigned_pair, nloaded_pair) in pairs.iter().zip(self.pairs.clone()) { let (scalar, x_limbs, y_limbs) = assigned_pair; - let (_, lpoint) = nloaded_pair; - let halo2_scalar = Halo2LScalar::new(scalar.clone(), loader_config.clone()); + let (lscalar, lpoint) = nloaded_pair; + let halo2_scalar = + Halo2LScalar::new((lscalar.inner, scalar.clone()), loader_config.clone()); - let x = AssignedInteger::new(lpoint.inner.x.clone(), x_limbs.clone()); - let y = AssignedInteger::new(lpoint.inner.y.clone(), y_limbs.clone()); + let x = AssignedInteger::new(lpoint.inner.x, x_limbs.clone()); + let y = AssignedInteger::new(lpoint.inner.y, y_limbs.clone()); let assigned_point = AssignedEcPoint::new(x, y); let halo2_point = Halo2LEcPoint::new(assigned_point, loader_config.clone()); diff --git a/eigentrust-zk/src/verifier/transcript/mod.rs b/eigentrust-zk/src/verifier/transcript/mod.rs index a8f00d2f..647827eb 100644 --- a/eigentrust-zk/src/verifier/transcript/mod.rs +++ b/eigentrust-zk/src/verifier/transcript/mod.rs @@ -3,7 +3,7 @@ use crate::{ ecc::same_curve::AssignedEcPoint, integer::{native::Integer, AssignedInteger}, params::{ecc::EccParams, rns::RnsParams}, - FieldExt, RegionCtx, SpongeHasherChipset, + FieldExt, RegionCtx, SpongeHasher, SpongeHasherChipset, }; use halo2::{ circuit::{Layouter, Region, Value}, @@ -34,10 +34,12 @@ pub struct TranscriptReadChipset< const NUM_BITS: usize, P, S, + H, EC, > where P: RnsParams, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, C::Base: FieldExt, C::Scalar: FieldExt, @@ -46,6 +48,8 @@ pub struct TranscriptReadChipset< reader: Option, // PoseidonSponge state: S, + // PoseidonSponge(native) + native_state: H, // Loader loader: LoaderConfig<'a, C, L, NUM_LIMBS, NUM_BITS, P, S, EC>, // PhantomData @@ -61,11 +65,13 @@ impl< const NUM_BITS: usize, P, S, + H, EC, - > TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, EC> + > TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, H, EC> where P: RnsParams, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, C::Base: FieldExt, C::Scalar: FieldExt, @@ -78,8 +84,9 @@ where let mut layouter_mut = loader.layouter.borrow_mut(); S::init(&loader.common, layouter_mut.namespace(|| "stateful_sponge")).unwrap() }; + let native_sponge = H::new(); - Self { reader, state: sponge, loader, _p: PhantomData } + Self { reader, state: sponge, native_state: native_sponge, loader, _p: PhantomData } } } @@ -92,12 +99,14 @@ impl< const NUM_BITS: usize, P, S, + H, EC, > Transcript> - for TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, EC> + for TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, H, EC> where P: RnsParams, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, C::Base: FieldExt, C::Scalar: FieldExt, @@ -122,7 +131,9 @@ where res }; - Halo2LScalar::new(result, self.loader.clone()) + let native_result = self.native_state.squeeze(); + + Halo2LScalar::new((native_result, result), self.loader.clone()) } /// Update with an elliptic curve point. @@ -132,6 +143,9 @@ where self.state.update(&ec_point.inner.x.limbs); self.state.update(&ec_point.inner.y.limbs); + self.native_state.update(&ec_point.inner.x.integer.limbs); + self.native_state.update(&ec_point.inner.y.integer.limbs); + Ok(()) } @@ -139,7 +153,9 @@ where fn common_scalar( &mut self, scalar: &Halo2LScalar, ) -> Result<(), snark_verifier::Error> { - self.state.update(&[scalar.inner.clone()]); + self.state.update(&[scalar.inner.1.clone()]); + + self.native_state.update(&[scalar.inner.0]); Ok(()) } @@ -154,12 +170,14 @@ impl< const NUM_BITS: usize, P, S, + H, EC, > TranscriptRead> - for TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, EC> + for TranscriptReadChipset<'a, RD, C, L, NUM_LIMBS, NUM_BITS, P, S, H, EC> where P: RnsParams, S: SpongeHasherChipset, + H: SpongeHasher, EC: EccParams, C::Base: FieldExt, C::Scalar: FieldExt, @@ -169,8 +187,8 @@ where &mut self, ) -> Result, VerifierError> { // Taking out reader from Value for a proper error handling - let scalar = self.reader.as_mut().map_or_else( - || Ok(Value::unknown()), + let (native_scalar, scalar) = self.reader.as_mut().map_or_else( + || Ok((C::Scalar::default(), Value::unknown())), |reader| { let mut data = ::Repr::default(); let res = reader.read_exact(data.as_mut()); @@ -191,7 +209,7 @@ where } let scalar = scalar_opt.unwrap(); - Ok(Value::known(scalar)) + Ok((scalar, Value::known(scalar))) }, )?; @@ -208,7 +226,8 @@ where ) .unwrap() }; - let assigned_lscalar = Halo2LScalar::new(assigned_scalar, self.loader.clone()); + let assigned_lscalar = + Halo2LScalar::new((native_scalar, assigned_scalar), self.loader.clone()); self.common_scalar(&assigned_lscalar)?; Ok(assigned_lscalar) @@ -314,7 +333,9 @@ where mod test { use super::{native::NativeTranscriptRead, LoaderConfig, TranscriptReadChipset}; use crate::{ - circuits::{FullRoundHasher, PartialRoundHasher}, + circuits::{ + FullRoundHasher, PartialRoundHasher, PoseidonNativeHasher, PoseidonNativeSponge, + }, ecc::{ same_curve::{native::EcPoint, AssignedEcPoint, UnassignedEcPoint}, AuxConfig, EccAddConfig, EccDoubleConfig, EccMulConfig, EccTableSelectConfig, @@ -364,6 +385,7 @@ mod test { type C = G1Affine; type P = Bn256_4_68; type S = StatefulSpongeChipset; + type H = PoseidonNativeSponge; type NativeH = PoseidonSponge; type Scalar = Fr; type Base = Fq; @@ -453,7 +475,7 @@ mod test { ); let reader = Vec::new(); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( Some(reader.as_slice()), loader, ); @@ -461,7 +483,7 @@ mod test { res.inner }; - layouter.constrain_instance(res.cell(), config.common.instance, 0)?; + layouter.constrain_instance(res.1.cell(), config.common.instance, 0)?; Ok(()) } @@ -495,11 +517,11 @@ mod test { fn new(ec_point: EcPoint) -> Self { let unassigned_x = UnassignedInteger::new( ec_point.x.clone(), - ec_point.x.limbs.map(|x| Value::known(x)), + ec_point.x.limbs.clone().map(|x| Value::known(x)), ); let unassigned_y = UnassignedInteger::new( ec_point.y.clone(), - ec_point.y.limbs.map(|y| Value::known(y)), + ec_point.y.limbs.clone().map(|y| Value::known(y)), ); let unassigned_ec_point = UnassignedEcPoint::new(unassigned_x, unassigned_y); @@ -571,7 +593,7 @@ mod test { let reader = Vec::new(); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( Some(reader.as_slice()), loader, ); @@ -582,7 +604,7 @@ mod test { res.inner }; - layouter.constrain_instance(res.clone().cell(), config.common.instance, 0)?; + layouter.constrain_instance(res.clone().1.cell(), config.common.instance, 0)?; Ok(()) } @@ -619,12 +641,13 @@ mod test { #[derive(Clone)] struct TestCommonScalarCircuit { + native_scalar: Scalar, scalar: Value, } impl TestCommonScalarCircuit { fn new(scalar: Scalar) -> Self { - Self { scalar: Value::known(scalar) } + Self { native_scalar: scalar, scalar: Value::known(scalar) } } } @@ -633,7 +656,7 @@ mod test { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self { scalar: Value::unknown() } + Self { native_scalar: self.native_scalar.clone(), scalar: Value::unknown() } } fn configure(meta: &mut ConstraintSystem) -> TestConfig { @@ -664,10 +687,11 @@ mod test { config.main, config.poseidon_sponge.clone(), ); - let scalar = Halo2LScalar::new(assigned_scalar, loader.clone()); + let scalar = + Halo2LScalar::new((self.native_scalar, assigned_scalar), loader.clone()); let reader = Vec::new(); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( Some(reader.as_slice()), loader, ); @@ -677,7 +701,7 @@ mod test { res.inner }; - layouter.constrain_instance(res.clone().cell(), config.common.instance, 0)?; + layouter.constrain_instance(res.clone().1.cell(), config.common.instance, 0)?; Ok(()) } @@ -744,7 +768,7 @@ mod test { ); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( self.reader.as_ref().map(|x| x.as_slice()), loader, ); @@ -752,7 +776,7 @@ mod test { res.inner }; - layouter.constrain_instance(scalar.cell(), config.common.instance, 0)?; + layouter.constrain_instance(scalar.1.cell(), config.common.instance, 0)?; Ok(()) } @@ -819,7 +843,7 @@ mod test { ); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( self.reader.as_ref().map(Vec::as_slice), loader, ); @@ -910,7 +934,7 @@ mod test { ); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( self.reader.as_ref().map(|x| x.as_slice()), loader, ); @@ -942,7 +966,7 @@ mod test { i += 1; } - layouter.constrain_instance(scalar1.cell(), config.common.instance, i)?; + layouter.constrain_instance(scalar1.1.cell(), config.common.instance, i)?; i += 1; for j in 0..NUM_LIMBS { @@ -954,7 +978,7 @@ mod test { i += 1; } - layouter.constrain_instance(scalar2.cell(), config.common.instance, i)?; + layouter.constrain_instance(scalar2.1.cell(), config.common.instance, i)?; Ok(()) } @@ -1043,7 +1067,7 @@ mod test { ); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( self.reader.as_ref().map(|x| x.as_slice()), loader, ); @@ -1057,7 +1081,7 @@ mod test { res.inner }; - layouter.constrain_instance(res.cell(), config.common.instance, 0)?; + layouter.constrain_instance(res.1.cell(), config.common.instance, 0)?; Ok(()) } @@ -1131,7 +1155,7 @@ mod test { ); let mut poseidon_read = - TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, EC>::new( + TranscriptReadChipset::<_, C, _, NUM_LIMBS, NUM_BITS, P, S, H, EC>::new( self.reader.as_ref().map(|x| x.as_slice()), loader, ); @@ -1145,7 +1169,7 @@ mod test { res.inner }; - layouter.constrain_instance(res.cell(), config.common.instance, 0)?; + layouter.constrain_instance(res.1.cell(), config.common.instance, 0)?; Ok(()) }