diff --git a/src/gadgets/ecc/mod.rs b/src/gadgets/ecc/mod.rs index 21ec4ae3..0080725d 100644 --- a/src/gadgets/ecc/mod.rs +++ b/src/gadgets/ecc/mod.rs @@ -1,12 +1,13 @@ use std::{cmp, marker::PhantomData}; +use rand_core::OsRng; use tracing::*; use crate::{ halo2_proofs::{ arithmetic::{CurveAffine, Field}, circuit::Chip, - halo2curves::ff::PrimeField, + halo2curves::ff::{PrimeField, PrimeFieldBits}, plonk::Error, }, main_gate::{AssignedValue, RegionCtx}, @@ -343,154 +344,158 @@ impl> EccChip { } } -#[cfg(test)] -pub(crate) mod tests { - use std::num::NonZeroUsize; +/// Auxiliary class that performs the off-circuit version of ecc gadget calculations +#[derive(Clone, Debug)] +pub(crate) struct Point { + x: C::Base, + y: C::Base, + is_inf: bool, +} +impl From for Point { + fn from(value: C) -> Self { + let c = value.coordinates().unwrap(); - use halo2_proofs::{circuit::Value, halo2curves::ff::PrimeFieldBits}; - use rand_core::OsRng; - use tracing_test::traced_test; + Self { + x: *c.x(), + y: *c.y(), + is_inf: value.is_identity().into(), + } + } +} - use super::*; - use crate::{ - create_and_verify_proof, - ff::Field, - halo2_proofs::{ - circuit::{Chip, Layouter, SimpleFloorPlanner}, - plonk::{Circuit, Column, ConstraintSystem, Instance}, - }, - halo2curves::pasta::{pallas, EqAffine, Fp, Fq}, - main_gate::{MainGate, MainGateConfig}, - run_mock_prover_test, - util::ScalarToBase, - }; +impl Point { + pub fn into_curve(self) -> C { + let Self { x, y, is_inf: _ } = self; + C::from_xy(x, y).unwrap() + } + pub fn into_pair(self) -> (C::Base, C::Base) { + (self.x, self.y) + } +} - #[derive(Clone, Debug)] - pub(crate) struct Point { - x: C::Base, - y: C::Base, - is_inf: bool, +impl Point { + fn default() -> Self { + Self { + x: C::Base::ZERO, + y: C::Base::ZERO, + is_inf: true, + } } - impl From for Point { - fn from(value: C) -> Self { - let c = value.coordinates().unwrap(); - Self { - x: *c.x(), - y: *c.y(), - is_inf: value.is_identity().into(), + /// Add any two points + pub fn add(&self, other: &Point) -> Self { + if self.x == other.x { + // If self == other then call double + if self.y == other.y { + self.double() + } else { + // if self.x == other.x and self.y != other.y then return infinity + Self { + x: C::Base::ZERO, + y: C::Base::ZERO, + is_inf: true, + } } + } else { + self.add_internal(other) } } - impl Point { - pub fn into_curve(self) -> C { - let Self { x, y, is_inf: _ } = self; - C::from_xy(x, y).unwrap() + /// Add two different points + pub fn add_internal(&self, other: &Point) -> Self { + if self.is_inf { + return other.clone(); + } + + if other.is_inf { + return self.clone(); + } + + let lambda = (other.y - self.y) * (other.x - self.x).invert().unwrap(); + let x = lambda * lambda - self.x - other.x; + let y = lambda * (self.x - x) - self.y; + Self { + x, + y, + is_inf: false, } } - impl Point { - fn default() -> Self { - Self { + pub fn double(&self) -> Self { + if self.is_inf { + return Self { x: C::Base::ZERO, y: C::Base::ZERO, is_inf: true, - } + }; } - /// Add any two points - pub fn add(&self, other: &Point) -> Self { - if self.x == other.x { - // If self == other then call double - if self.y == other.y { - self.double() - } else { - // if self.x == other.x and self.y != other.y then return infinity - Self { - x: C::Base::ZERO, - y: C::Base::ZERO, - is_inf: true, - } - } - } else { - self.add_internal(other) - } + let lambda = C::Base::from(3) + * self.x + * self.x + * ((C::Base::ONE + C::Base::ONE) * self.y).invert().unwrap(); + let x = lambda * lambda - self.x - self.x; + let y = lambda * (self.x - x) - self.y; + Self { + x, + y, + is_inf: false, } + } - /// Add two different points - pub fn add_internal(&self, other: &Point) -> Self { - if self.is_inf { - return other.clone(); - } - - if other.is_inf { - return self.clone(); - } + pub fn scalar_mul(&self, scalar: &F) -> Self { + let mut res = Self { + x: C::Base::ZERO, + y: C::Base::ZERO, + is_inf: true, + }; - let lambda = (other.y - self.y) * (other.x - self.x).invert().unwrap(); - let x = lambda * lambda - self.x - other.x; - let y = lambda * (self.x - x) - self.y; - Self { - x, - y, - is_inf: false, + let bits = scalar.to_le_bits(); + for i in (0..bits.len()).rev() { + res = res.double(); + if bits[i] { + res = self.add(&res); } } + res + } - pub fn double(&self) -> Self { - if self.is_inf { + fn random_vartime() -> Self { + loop { + let x = C::Base::random(&mut OsRng); + let y = (x.square() * x + C::b()).sqrt(); + if y.is_some().unwrap_u8() == 1 { return Self { - x: C::Base::ZERO, - y: C::Base::ZERO, - is_inf: true, + x, + y: y.unwrap(), + is_inf: false, }; } - - let lambda = C::Base::from(3) - * self.x - * self.x - * ((C::Base::ONE + C::Base::ONE) * self.y).invert().unwrap(); - let x = lambda * lambda - self.x - self.x; - let y = lambda * (self.x - x) - self.y; - Self { - x, - y, - is_inf: false, - } } + } +} - pub fn scalar_mul(&self, scalar: &F) -> Self { - let mut res = Self { - x: C::Base::ZERO, - y: C::Base::ZERO, - is_inf: true, - }; +#[cfg(test)] +pub(crate) mod tests { + use std::num::NonZeroUsize; - let bits = scalar.to_le_bits(); - for i in (0..bits.len()).rev() { - res = res.double(); - if bits[i] { - res = self.add(&res); - } - } - res - } + use halo2_proofs::{circuit::Value, halo2curves::ff::PrimeFieldBits}; + use rand_core::OsRng; + use tracing_test::traced_test; - fn random_vartime() -> Self { - loop { - let x = C::Base::random(&mut OsRng); - let y = (x.square() * x + C::b()).sqrt(); - if y.is_some().unwrap_u8() == 1 { - return Self { - x, - y: y.unwrap(), - is_inf: false, - }; - } - } - } - } + use super::*; + use crate::{ + create_and_verify_proof, + ff::Field, + halo2_proofs::{ + circuit::{Chip, Layouter, SimpleFloorPlanner}, + plonk::{Circuit, Column, ConstraintSystem, Instance}, + }, + halo2curves::pasta::{pallas, EqAffine, Fp, Fq}, + main_gate::{MainGate, MainGateConfig}, + run_mock_prover_test, + util::ScalarToBase, + }; const T: usize = 4; #[derive(Clone, Debug)] diff --git a/src/ivc/cyclefold/incrementally_verifiable_computation/public_params.rs b/src/ivc/cyclefold/incrementally_verifiable_computation/public_params.rs index 575f8805..e1f5f4f7 100644 --- a/src/ivc/cyclefold/incrementally_verifiable_computation/public_params.rs +++ b/src/ivc/cyclefold/incrementally_verifiable_computation/public_params.rs @@ -83,7 +83,6 @@ where l0: CMain::Base::ZERO, p1: CMain::identity(), l1: CMain::Base::ZERO, - p_out: CMain::identity(), } .into_instance(); diff --git a/src/ivc/cyclefold/support_circuit/mod.rs b/src/ivc/cyclefold/support_circuit/mod.rs index 8b2e2a94..09b27963 100644 --- a/src/ivc/cyclefold/support_circuit/mod.rs +++ b/src/ivc/cyclefold/support_circuit/mod.rs @@ -3,7 +3,7 @@ use std::{marker::PhantomData, num::NonZeroUsize}; use tracing::*; use crate::{ - gadgets::ecc, + gadgets::ecc::{self, Point}, halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, halo2curves::{ @@ -34,8 +34,6 @@ pub struct InstanceInput { pub p1: C, pub l1: C::Base, - - pub p_out: C, } impl InstanceInput @@ -45,11 +43,15 @@ where pub fn into_instance(self) -> Vec> { let p0 = self.p0.coordinates().unwrap(); let p1 = self.p1.coordinates().unwrap(); - let p_out = self.p_out.coordinates().unwrap(); + + let (p_out_x, p_out_y) = Point::from(self.p0) + .scalar_mul(&self.l0) + .add(&Point::from(self.p1).scalar_mul(&self.l1)) + .into_pair(); let instance: [C::Base; INSTANCES_LEN] = [ - *p_out.x(), - *p_out.y(), + p_out_x, + p_out_y, *p0.x(), *p0.y(), self.l0, @@ -163,7 +165,6 @@ mod tests { use super::*; use crate::{ - gadgets::ecc::tests::Point, halo2_proofs::dev::MockProver, prelude::{bn256::C1Affine as Curve, Field}, }; @@ -189,22 +190,10 @@ mod tests { let l0 = Base::from_repr(l0.to_repr()).unwrap(); let l1 = Base::from_repr(l1.to_repr()).unwrap(); - let p_out = Point::from(p0) - .scalar_mul(&l0) - .add(&Point::from(p1).scalar_mul(&l1)) - .into_curve(); - MockProver::run( SupportCircuit::::MIN_K_TABLE_SIZE, &circuit, - InstanceInput { - p0, - l0, - p1, - l1, - p_out, - } - .into_instance(), + InstanceInput { p0, l0, p1, l1 }.into_instance(), ) .unwrap() .verify()