diff --git a/Cargo.toml b/Cargo.toml index a0a5a1f6..980dc5b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,10 @@ members = [ "ecdsa", "transcript" ] + + +[patch."https://github.com/privacy-scaling-explorations/halo2.git"] +halo2_proofs = { git = "https://github.com/davidnevadoc/halo2.git", branch = "test/feat-curve-endo" } + +[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] +halo2curves = { git = "https://github.com/davidnevadoc/halo2curves.git", branch = "test/endo-export" } diff --git a/ecc/Cargo.toml b/ecc/Cargo.toml index 5f221e20..7b1c9869 100644 --- a/ecc/Cargo.toml +++ b/ecc/Cargo.toml @@ -10,7 +10,6 @@ num-bigint = { version = "0.4", features = ["rand"] } num-integer = "0.1" num-traits = "0.2" rand = "0.8" -group = "0.12" subtle = { version = "2.3", default-features = false } [dev-dependencies] diff --git a/ecc/src/base_field_ecc.rs b/ecc/src/base_field_ecc.rs index a79ac760..119df646 100644 --- a/ecc/src/base_field_ecc.rs +++ b/ecc/src/base_field_ecc.rs @@ -2,10 +2,11 @@ use super::{make_mul_aux, AssignedPoint, EccConfig, MulAux, Point}; use crate::integer::chip::IntegerChip; use crate::integer::rns::{Integer, Rns}; use crate::{halo2, maingate}; -use halo2::arithmetic::CurveAffine; +use halo2::arithmetic::{CurveAffine, CurveEndo}; use halo2::circuit::Layouter; use halo2::plonk::Error; use integer::halo2::circuit::Value; +use integer::halo2::ff::WithSmallOrderMulGroup; use integer::maingate::{MainGateInstructions, RegionCtx}; use integer::{IntegerInstructions, Range}; use maingate::{AssignedCondition, MainGate}; @@ -24,17 +25,54 @@ pub struct BaseFieldEccChip, + /// Auxiliary point for optimized multiplication algorithm aux_generator: Option<( AssignedPoint, Value, )>, - /// Auxiliary points for optimized multiplication for each (window_size, - /// n_pairs) pairs + + /// Auxiliary points for optimized multiplication for each + /// (window_size, n_pairs) pairs aux_registry: BTreeMap<(usize, usize), AssignedPoint>, } +/// Elliptic Curve instructions that use the emulated curve efficient endomorphism. +#[derive(Debug, Clone)] +pub struct BaseFieldEndoEccChip< + C: CurveEndo, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { + ecc_chip: BaseFieldEccChip, +} + +impl + BaseFieldEndoEccChip +{ + /// Return `EndoEccChip` from `EccChip` + pub fn new(ecc_chip: BaseFieldEccChip) -> Self { + Self { ecc_chip } + } +} + +impl + BaseFieldEccChip +{ + /// Computes the endomorphism of a given point using one base field multplication. + pub fn endo( + &self, + ctx: &mut RegionCtx<'_, C::Scalar>, + point: &AssignedPoint, + ) -> Result, Error> { + let integer_chip = self.integer_chip(); + let zeta = Integer::from_fe(C::Base::ZETA, self.rns()); + let x = integer_chip.mul_constant(ctx, point.x(), &zeta)?; + Ok(AssignedPoint::new(x, point.y().clone())) + } +} + impl BaseFieldEccChip { @@ -101,11 +139,7 @@ impl // see https://hackmd.io/ncuKqRXzR-Cw-Au2fGzsMg?view Ok(MulAux::new(to_add, to_sub)) } -} -impl - BaseFieldEccChip -{ /// Expose `AssignedPoint` as Public Input pub fn expose_public( &self, @@ -182,10 +216,12 @@ impl ctx: &mut RegionCtx<'_, C::Scalar>, window_size: usize, number_of_pairs: usize, + n_bits: usize, // number of bits of the scalar ) -> Result<(), Error> { match self.aux_generator { Some((_, point)) => { - let aux = point.map(|point| make_mul_aux(point, window_size, number_of_pairs)); + let aux = + point.map(|point| make_mul_aux(point, window_size, number_of_pairs, n_bits)); let aux = self.assign_point(ctx, aux)?; self.aux_registry .insert((window_size, number_of_pairs), aux); @@ -340,10 +376,8 @@ impl #[cfg(test)] mod tests { - use std::marker::PhantomData; - use std::rc::Rc; - use super::BaseFieldEccChip; + use super::BaseFieldEndoEccChip; use super::{AssignedPoint, EccConfig, Point}; use crate::curves::bn256::G1Affine as Bn256; use crate::curves::pasta::{EpAffine as Pallas, EqAffine as Vesta}; @@ -351,10 +385,13 @@ mod tests { use crate::integer::rns::Rns; use crate::integer::NUMBER_OF_LOOKUP_LIMBS; use crate::maingate; - use group::{Curve as _, Group}; - use halo2::arithmetic::{CurveAffine, FieldExt}; + use halo2::arithmetic::CurveAffine; use halo2::circuit::{Layouter, SimpleFloorPlanner, Value}; use halo2::plonk::{Circuit, ConstraintSystem, Error}; + use integer::halo2::curves::CurveEndo; + use integer::halo2::ff::{Field, FromUniformBytes, PrimeField}; + use integer::halo2::group::Curve; + use integer::halo2::group::Group; use integer::maingate::RegionCtx; use maingate::mock_prover_verify; use maingate::{ @@ -363,6 +400,8 @@ mod tests { }; use paste::paste; use rand_core::OsRng; + use std::marker::PhantomData; + use std::rc::Rc; const NUMBER_OF_LIMBS: usize = 4; const BIT_LEN_LIMB: usize = 68; @@ -419,7 +458,10 @@ mod tests { } } - fn config_range(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + fn config_range( + &self, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { let range_chip = RangeChip::::new(self.range_config.clone()); range_chip.load_table(layouter)?; @@ -505,7 +547,10 @@ mod tests { #[test] fn test_base_field_ecc_addition_circuit() { - fn run() { + fn run() + where + C::Scalar: FromUniformBytes<64>, + { let circuit = TestEccAddition::::default(); let instance = vec![vec![]]; mock_prover_verify(&circuit, instance); @@ -580,7 +625,10 @@ mod tests { #[test] fn test_base_field_ecc_public_input() { - fn run() { + fn run() + where + C::Scalar: FromUniformBytes<64>, + { let (rns, _) = setup::(20); let rns = Rc::new(rns); @@ -641,7 +689,7 @@ mod tests { let offset = 0; let ctx = &mut RegionCtx::new(region, offset); ecc_chip.assign_aux_generator(ctx, Value::known(self.aux_generator))?; - ecc_chip.assign_aux(ctx, self.window_size, 1)?; + ecc_chip.assign_aux(ctx, self.window_size, 1, C::Scalar::NUM_BITS as usize)?; ecc_chip.get_mul_aux(self.window_size, 1)?; Ok(()) }, @@ -650,7 +698,6 @@ mod tests { layouter.assign_region( || "region 0", |region| { - use group::ff::Field; let offset = 0; let ctx = &mut RegionCtx::new(region, offset); @@ -677,7 +724,10 @@ mod tests { #[test] fn test_base_field_ecc_mul_circuit() { - fn run() { + fn run() + where + C::Scalar: FromUniformBytes<64>, + { for window_size in 1..5 { let aux_generator = ::CurveExt::random(OsRng).to_affine(); @@ -730,7 +780,12 @@ mod tests { let offset = 0; let ctx = &mut RegionCtx::new(region, offset); ecc_chip.assign_aux_generator(ctx, Value::known(self.aux_generator))?; - ecc_chip.assign_aux(ctx, self.window_size, self.number_of_pairs)?; + ecc_chip.assign_aux( + ctx, + self.window_size, + self.number_of_pairs, + C::Scalar::NUM_BITS as usize, + )?; ecc_chip.get_mul_aux(self.window_size, self.number_of_pairs)?; Ok(()) }, @@ -739,7 +794,6 @@ mod tests { layouter.assign_region( || "region 0", |region| { - use group::ff::Field; let offset = 0; let ctx = &mut RegionCtx::new(region, offset); @@ -799,4 +853,115 @@ mod tests { test_base_field_ecc_mul_batch_circuit!(Bn256); test_base_field_ecc_mul_batch_circuit!(Pallas); test_base_field_ecc_mul_batch_circuit!(Vesta); + + #[derive(Default, Clone, Debug)] + struct TestEccEndoMul { + window_size: usize, + aux_generator: C::AffineExt, + } + + impl Circuit<::ScalarExt> for TestEccEndoMul { + type Config = TestCircuitConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + unimplemented!(); + } + + fn configure( + meta: &mut ConstraintSystem<::ScalarExt>, + ) -> Self::Config { + TestCircuitConfig::new::(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter<::ScalarExt>, + ) -> Result<(), Error> { + let ecc_chip_config = config.ecc_chip_config(); + let mut ecc_endo_chip = + BaseFieldEndoEccChip::::new(BaseFieldEccChip::< + C::AffineExt, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >::new( + ecc_chip_config + )); + + let main_gate = MainGate::::new(config.main_gate_config.clone()); + + layouter.assign_region( + || "assign aux values", + |region| { + let offset = 0; + let ctx = &mut RegionCtx::new(region, offset); + ecc_endo_chip + .ecc_chip + .assign_aux_generator(ctx, Value::known(self.aux_generator))?; + // we set n_pairs=2 because the scalar is split into 2 128-bit scalars + ecc_endo_chip + .ecc_chip + .assign_aux(ctx, self.window_size, 2, 128)?; + ecc_endo_chip.ecc_chip.get_mul_aux(self.window_size, 2)?; + Ok(()) + }, + )?; + + layouter.assign_region( + || "region 0", + |region| { + let offset = 0; + let ctx = &mut RegionCtx::new(region, offset); + + let base = C::random(OsRng); + let s = C::ScalarExt::random(OsRng); + let result = base * s; + + let base = ecc_endo_chip + .ecc_chip + .assign_point(ctx, Value::known(base.into()))?; + let s = main_gate.assign_value(ctx, Value::known(s))?; + + let result_0 = ecc_endo_chip + .ecc_chip + .assign_point(ctx, Value::known(result.into()))?; + + let result_1 = ecc_endo_chip.glv_mul(ctx, &base, &s, self.window_size)?; + ecc_endo_chip + .ecc_chip + .assert_equal(ctx, &result_0, &result_1)?; + + Ok(()) + }, + )?; + + config.config_range(&mut layouter)?; + + Ok(()) + } + } + + #[test] + fn test_base_field_ecc_endo_mul_circuit() { + fn run() + where + ::ScalarExt: FromUniformBytes<64> + Ord, + { + for window_size in 2..4 { + let aux_generator = C::random(OsRng).to_affine(); + + let circuit = TestEccEndoMul:: { + aux_generator, + window_size, + }; + let instance: Vec::ScalarExt>> = vec![vec![]]; + mock_prover_verify(&circuit, instance); + } + } + + run::(); // G1 + run::(); // Vesta + run::(); // Pallas + } } diff --git a/ecc/src/base_field_ecc/mul.rs b/ecc/src/base_field_ecc/mul.rs index 96aa89be..6920a0a1 100644 --- a/ecc/src/base_field_ecc/mul.rs +++ b/ecc/src/base_field_ecc/mul.rs @@ -1,10 +1,11 @@ -use super::{AssignedPoint, BaseFieldEccChip}; +use super::{AssignedPoint, BaseFieldEccChip, BaseFieldEndoEccChip}; use crate::maingate::{AssignedCondition, AssignedValue, MainGateInstructions}; -use crate::{halo2, Selector, Table, Windowed}; -use group::ff::PrimeField; +use crate::{halo2, AssignedDecompScalar, Selector, Table, Windowed}; use halo2::arithmetic::CurveAffine; +use halo2::arithmetic::CurveEndo; use halo2::plonk::Error; -use integer::maingate::RegionCtx; +use integer::halo2::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use integer::maingate::{CombinationOption, RegionCtx, Term}; impl BaseFieldEccChip @@ -16,14 +17,13 @@ impl bits: &mut Vec>, window_size: usize, ) -> Result<(), Error> { - use group::ff::Field; - assert_eq!(bits.len(), C::Scalar::NUM_BITS as usize); + // assert_eq!(bits.len(), C::Scalar::NUM_BITS as usize); // TODO: This is a tmp workaround. Instead of padding with zeros we can use a // shorter ending window. let padding_offset = (window_size - (bits.len() % window_size)) % window_size; let zeros: Vec> = (0..padding_offset) - .map(|_| self.main_gate().assign_constant(ctx, C::Scalar::zero())) + .map(|_| self.main_gate().assign_constant(ctx, C::Scalar::ZERO)) .collect::>()?; bits.extend(zeros); bits.reverse(); @@ -194,3 +194,156 @@ impl self.add(ctx, &acc, &aux.to_sub) } } + +impl + BaseFieldEndoEccChip +{ + /// Split a scalar k in 128-bit scalars k1, k2 such that: + /// k = k1 - C::lambda * k2 + fn split_scalar( + &self, + ctx: &mut RegionCtx<'_, C::Scalar>, + scalar: &AssignedValue, + ) -> Result, Error> { + let maingate = self.ecc_chip.main_gate(); + let sig = |neg: bool| if neg { -C::Scalar::ONE } else { C::Scalar::ONE }; + + let decomposed = scalar.value().map(|v| C::decompose_scalar(v)); + + let k1 = decomposed.map(|decomp| C::Scalar::from_u128(decomp.0)); + let k1_sig = decomposed.map(|decomp| sig(decomp.1)); + + let k2 = decomposed.map(|decomp| C::Scalar::from_u128(decomp.2)); + let k2_sig = decomposed.map(|decomp| sig(decomp.3)); + + // Sanity check + scalar.value().map(|s| dbg!(s)); + decomposed.map(|(k1, k1_neg, k2, k2_neg)| { + let k1 = C::Scalar::from_u128(k1); + let k2 = C::Scalar::from_u128(k2); + let k1_sig = sig(k1_neg); + let k2_sig = sig(k2_neg); + dbg!(k1, k2, k1_sig, k2_sig); + scalar + .value() + .map(|k| assert_eq!(k1 * k1_sig - C::ScalarExt::ZETA * k2 * k2_sig, *k)); + }); + + // Add decomoposition constraint + // k1 * k1_sig - C::LAMBDA * k2 * k2_sig - k = 0 + // k1_sig i {-1, 1} + // k2_sig i {-1, 1} + + // Maingate can be used directly, C::Scalar is the native field + let assigned = maingate.apply( + ctx, + [ + Term::unassigned_to_mul(k1), + Term::unassigned_to_mul(k1_sig), + Term::unassigned_to_mul(k2), + Term::unassigned_to_mul(k2_sig), + Term::assigned_to_sub(scalar), + ], + C::Scalar::ZERO, + CombinationOption::OneLinerDoubleMul(-C::ScalarExt::ZETA), + )?; + let (k1, k1_sig, k2, k2_sig) = (&assigned[0], &assigned[1], &assigned[2], &assigned[3]); + maingate.assert_sign(ctx, &k1_sig)?; + maingate.assert_sign(ctx, &k2_sig)?; + + let k1_pos = maingate.sign_to_cond(ctx, k1_sig)?; + let k2_pos = maingate.sign_to_cond(ctx, k2_sig)?; + + Ok([(k1.clone(), k1_pos.clone()), (k2.clone(), k2_pos.clone())]) + } + + /// Scalar multiplication of a point in the EC + /// Performed with the sliding-window algorithm + pub fn glv_mul( + &self, + ctx: &mut RegionCtx<'_, C::Scalar>, + point: &AssignedPoint< + ::Base, + ::ScalarExt, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >, + scalar: &AssignedValue, + window_size: usize, + ) -> Result< + AssignedPoint< + ::Base, + ::ScalarExt, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >, + Error, + > { + assert!(window_size > 0); + let ecc = &self.ecc_chip; + let aux = ecc.get_mul_aux(window_size, 2)?; + + // 1. Decompose scalar k -> k1, k2 + let split = self.split_scalar(ctx, scalar)?; + + // 2. Decompose scalars into AssignedCondition + let main_gate = ecc.main_gate(); + let decomp_k1 = &mut main_gate.to_bits(ctx, &split[0].0, 128usize)?; + let decomp_k2 = &mut main_gate.to_bits(ctx, &split[1].0, 128usize)?; + + // 2.1 Convert signs into Integers + let minus_point = ecc.neg(ctx, point)?; + let k1_point = ecc.select(ctx, &split[0].1, point, &minus_point)?; + let k2_point = ecc.select(ctx, &split[1].1, &minus_point, point)?; + let k2_point = ecc.endo(ctx, &k2_point)?; + + // 3. Pad to window size and chunk in windows + ecc.pad(ctx, decomp_k1, window_size)?; + ecc.pad(ctx, decomp_k2, window_size)?; + + let windowed_k1 = BaseFieldEccChip::::window( + decomp_k1.to_vec(), + window_size, + ); + let windowed_k2 = BaseFieldEccChip::::window( + decomp_k2.to_vec(), + window_size, + ); + let number_of_windows = windowed_k1.0.len(); + + // 4. Generate aux acc point + Generate table + let mut binary_aux = aux.to_add.clone(); + let tables: Vec> = vec![k1_point, k2_point] + .iter() + .enumerate() + .map(|(i, point)| { + let table = ecc.make_incremental_table(ctx, &binary_aux, point, window_size); + if i != 1 { + binary_aux = ecc.double(ctx, &binary_aux)?; + } + table + }) + .collect::>()?; + + // 5. Mul double-and-add algorithm + let windowed_scalars = vec![windowed_k1, windowed_k2]; + + let mut acc = ecc.select_multi(ctx, &windowed_scalars[0].0[0], &tables[0])?; + // add first contributions other point scalar + for (table, windowed) in tables.iter().skip(1).zip(windowed_scalars.iter().skip(1)) { + let selector = &windowed.0[0]; + let to_add = ecc.select_multi(ctx, selector, table)?; + acc = ecc.add(ctx, &acc, &to_add)?; + } + + for i in 1..number_of_windows { + acc = ecc.double_n(ctx, &acc, window_size)?; + for (table, windowed) in tables.iter().zip(windowed_scalars.iter()) { + let selector = &windowed.0[i]; + let to_add = ecc.select_multi(ctx, selector, table)?; + acc = ecc.add(ctx, &acc, &to_add)?; + } + } + ecc.add(ctx, &acc, &aux.to_sub) + } +} diff --git a/ecc/src/ecc.rs b/ecc/src/ecc.rs index b7365a2e..2896b808 100644 --- a/ecc/src/ecc.rs +++ b/ecc/src/ecc.rs @@ -1,9 +1,9 @@ -use crate::halo2::arithmetic::{CurveAffine, FieldExt}; +use crate::halo2::arithmetic::{CurveAffine, PrimeField}; use crate::integer::chip::IntegerConfig; use crate::integer::rns::{Integer, Rns}; use crate::integer::AssignedInteger; use crate::maingate::{big_to_fe, Assigned, AssignedCondition, MainGateConfig, RangeConfig}; -use crate::FieldExt; +use crate::PrimeField; use group::Curve; use num_bigint::BigUint as big_uint; use num_traits::One; @@ -12,13 +12,17 @@ use std::rc::Rc; /// Represent a Point in affine coordinates #[derive(Clone, Debug)] -pub struct Point -{ +pub struct Point< + W: PrimeField, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { x: Integer, y: Integer, } -impl +impl Point { /// Returns `Point` form a point in a EC with W as its base field @@ -58,8 +62,8 @@ impl { @@ -67,8 +71,8 @@ pub struct AssignedPoint< pub(crate) y: AssignedInteger, } -impl fmt::Debug - for AssignedPoint +impl + fmt::Debug for AssignedPoint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("AssignedPoint") @@ -79,7 +83,7 @@ impl +impl AssignedPoint { /// Returns a new `AssignedPoint` given its coordinates as `AssignedInteger` @@ -166,9 +170,9 @@ pub(crate) fn make_mul_aux( /// Allows to select values of precomputed table in efficient multiplication /// algorithm #[derive(Default)] -pub(crate) struct Selector(Vec>); +pub(crate) struct Selector(Vec>); -impl fmt::Debug for Selector { +impl fmt::Debug for Selector { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Selector"); for (i, bit) in self.0.iter().enumerate() { @@ -181,9 +185,9 @@ impl fmt::Debug for Selector { /// Vector of `Selectors` which represent the binary representation of a scalar /// split in window sized selectors. -pub(crate) struct Windowed(Vec>); +pub(crate) struct Windowed(Vec>); -impl fmt::Debug for Windowed { +impl fmt::Debug for Windowed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Window"); for (i, selector) in self.0.iter().enumerate() { @@ -198,14 +202,14 @@ impl fmt::Debug for Windowed { /// Table of precomputed values for efficient multiplication algorithm. pub(crate) struct Table< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >(pub(crate) Vec>); -impl fmt::Debug - for Table +impl + fmt::Debug for Table { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Table"); @@ -223,8 +227,8 @@ impl { @@ -233,7 +237,7 @@ pub(super) struct MulAux< } /// Constructs `MulAux` -impl +impl MulAux { pub(super) fn new( diff --git a/ecc/src/general_ecc.rs b/ecc/src/general_ecc.rs index 49e08cca..15c26057 100644 --- a/ecc/src/general_ecc.rs +++ b/ecc/src/general_ecc.rs @@ -3,9 +3,11 @@ use crate::halo2; use crate::integer::rns::{Integer, Rns}; use crate::integer::{IntegerChip, IntegerInstructions, Range, UnassignedInteger}; use crate::maingate; -use halo2::arithmetic::{CurveAffine, FieldExt}; +use halo2::arithmetic::CurveAffine; use halo2::circuit::{Layouter, Value}; use halo2::plonk::Error; +use integer::halo2::curves::CurveEndo; +use integer::halo2::ff::{PrimeField, WithSmallOrderMulGroup}; use integer::maingate::RegionCtx; use maingate::{AssignedCondition, MainGate}; use std::collections::BTreeMap; @@ -20,7 +22,7 @@ mod mul; #[allow(clippy::type_complexity)] pub struct GeneralEccChip< Emulated: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -39,9 +41,55 @@ pub struct GeneralEccChip< BTreeMap<(usize, usize), AssignedPoint>, } +/// Elliptic Curve instructions that use the emulated curve efficient endomorphism. +#[derive(Debug, Clone)] +pub struct GeneralEndoEccChip< + Emulated: CurveEndo, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { + ecc_chip: GeneralEccChip, +} + +impl< + Emulated: CurveEndo, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > GeneralEndoEccChip +{ + /// Return `EndoEccChip` from `EccChip` + pub fn new( + ecc_chip: GeneralEccChip, + ) -> Self { + Self { ecc_chip } + } +} + impl< Emulated: CurveAffine, - N: FieldExt, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > GeneralEccChip +{ + /// Computes the endomorphism of a given point using one base field multplication. + pub fn endo( + &self, + ctx: &mut RegionCtx<'_, N>, + point: &AssignedPoint, + ) -> Result, Error> { + let integer_chip = self.base_field_chip(); + let zeta = Integer::from_fe(Emulated::Base::ZETA, integer_chip.rns()); + let x = integer_chip.mul_constant(ctx, point.x(), &zeta)?; + Ok(AssignedPoint::new(x, point.y().clone())) + } +} + +impl< + Emulated: CurveAffine, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > GeneralEccChip @@ -158,7 +206,7 @@ impl< impl< Emulated: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > GeneralEccChip @@ -241,10 +289,12 @@ impl< ctx: &mut RegionCtx<'_, N>, window_size: usize, number_of_pairs: usize, + n_bits: usize, // number of bits of the scalar ) -> Result<(), Error> { match self.aux_generator { Some((_, point)) => { - let aux = point.map(|point| make_mul_aux(point, window_size, number_of_pairs)); + let aux = + point.map(|point| make_mul_aux(point, window_size, number_of_pairs, n_bits)); let aux = self.assign_point(ctx, aux)?; self.aux_registry .insert((window_size, number_of_pairs), aux); @@ -395,15 +445,18 @@ mod tests { use std::rc::Rc; use super::{AssignedPoint, EccConfig, GeneralEccChip, Point}; - use crate::halo2; use crate::integer::rns::Rns; use crate::integer::NUMBER_OF_LOOKUP_LIMBS; use crate::integer::{AssignedInteger, IntegerInstructions}; use crate::maingate; - use group::{prime::PrimeCurveAffine, Curve as _, Group}; - use halo2::arithmetic::{CurveAffine, FieldExt}; + use crate::{halo2, GeneralEndoEccChip}; + use halo2::arithmetic::CurveAffine; use halo2::circuit::{Layouter, SimpleFloorPlanner, Value}; use halo2::plonk::{Circuit, ConstraintSystem, Error}; + use integer::halo2::curves::CurveEndo; + use integer::halo2::ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; + use integer::halo2::group::{Curve, Group}; + use integer::maingate::MainGateInstructions; use integer::rns::Integer; use integer::Range; use maingate::mock_prover_verify; @@ -425,7 +478,7 @@ mod tests { #[allow(clippy::type_complexity)] fn setup< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >( @@ -462,7 +515,7 @@ mod tests { impl TestCircuitConfig { fn new< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >( @@ -490,7 +543,10 @@ mod tests { } } - fn config_range(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + fn config_range( + &self, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { let range_chip = RangeChip::::new(self.range_config.clone()); range_chip.load_table(layouter)?; @@ -501,15 +557,19 @@ mod tests { #[derive(Clone, Debug, Default)] struct TestEccAddition< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { _marker: PhantomData<(C, N)>, } - impl - Circuit for TestEccAddition + impl< + C: CurveAffine, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > Circuit for TestEccAddition { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -585,7 +645,7 @@ mod tests { fn test_general_ecc_addition_circuit() { fn run< C: CurveAffine, - N: FieldExt, + N: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >() { @@ -614,7 +674,7 @@ mod tests { #[derive(Default, Clone, Debug)] struct TestEccPublicInput< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -623,8 +683,12 @@ mod tests { _marker: PhantomData, } - impl - Circuit for TestEccPublicInput + impl< + C: CurveAffine, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > Circuit for TestEccPublicInput { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -686,7 +750,7 @@ mod tests { fn test_general_ecc_public_input() { fn run< C: CurveAffine, - N: FieldExt, + N: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >() { @@ -731,7 +795,7 @@ mod tests { #[derive(Default, Clone, Debug)] struct TestEccMul< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -740,8 +804,12 @@ mod tests { _marker: PhantomData, } - impl - Circuit for TestEccMul + impl< + C: CurveAffine, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > Circuit for TestEccMul { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -769,7 +837,12 @@ mod tests { let offset = 0; let ctx = &mut RegionCtx::new(region, offset); ecc_chip.assign_aux_generator(ctx, Value::known(self.aux_generator))?; - ecc_chip.assign_aux(ctx, self.window_size, 1)?; + ecc_chip.assign_aux( + ctx, + self.window_size, + 1, + C::ScalarExt::NUM_BITS as usize, + )?; ecc_chip.get_mul_aux(self.window_size, 1)?; Ok(()) }, @@ -780,7 +853,6 @@ mod tests { layouter.assign_region( || "region mul", |region| { - use group::ff::Field; let offset = 0; let ctx = &mut RegionCtx::new(region, offset); @@ -798,6 +870,8 @@ mod tests { let result_0 = ecc_chip.assign_point(ctx, Value::known(result.into()))?; let result_1 = ecc_chip.mul(ctx, &base, &s, self.window_size)?; + let maingate = ecc_chip.main_gate(); + maingate.break_here(ctx)?; ecc_chip.assert_equal(ctx, &result_0, &result_1)?; Ok(()) @@ -814,11 +888,11 @@ mod tests { fn test_general_ecc_mul_circuit() { fn run< C: CurveAffine, - N: FieldExt, + N: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >() { - for window_size in 1..5 { + for window_size in 2..3 { let aux_generator = C::Curve::random(OsRng).to_affine(); let circuit = TestEccMul:: { @@ -843,15 +917,152 @@ mod tests { run::(); run::(); - run::(); - run::(); - run::(); + // run::(); + // run::(); + // run::(); + } + + #[derive(Default, Clone, Debug)] + struct TestEccEndoMul< + C: CurveEndo, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > { + window_size: usize, + aux_generator: C, + _marker: PhantomData, + } + + impl + Circuit for TestEccEndoMul + { + type Config = TestCircuitConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + unimplemented!() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + TestCircuitConfig::new::(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let ecc_chip_config = config.ecc_chip_config(); + let mut ecc_endo_chip = + GeneralEndoEccChip::::new(GeneralEccChip::< + C::AffineExt, + N, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >::new( + ecc_chip_config + )); + // let &mut ecc_chip = ecc_endo_chip.ecc_chip; + + layouter.assign_region( + || "assign aux values", + |region| { + let offset = 0; + let ctx = &mut RegionCtx::new(region, offset); + ecc_endo_chip + .ecc_chip + .assign_aux_generator(ctx, Value::known(self.aux_generator.to_affine()))?; + ecc_endo_chip + .ecc_chip + .assign_aux(ctx, self.window_size, 2, 128)?; + ecc_endo_chip.ecc_chip.get_mul_aux(self.window_size, 2)?; + Ok(()) + }, + )?; + + let scalar_chip = ecc_endo_chip.ecc_chip.scalar_field_chip(); + + layouter.assign_region( + || "region mul", + |region| { + let offset = 0; + let ctx = &mut RegionCtx::new(region, offset); + + let base = C::random(OsRng); + let s = C::Scalar::random(OsRng); + let result = base * s; + + let s = Integer::from_fe(s, ecc_endo_chip.ecc_chip.rns_scalar()); + let base = ecc_endo_chip + .ecc_chip + .assign_point(ctx, Value::known(base.into()))?; + let s = scalar_chip.assign_integer( + ctx, + Value::known(s).into(), + Range::Remainder, + )?; + let result_0 = ecc_endo_chip + .ecc_chip + .assign_point(ctx, Value::known(result.into()))?; + + let result_1 = ecc_endo_chip.glv_mul(ctx, &base, &s, self.window_size)?; + ecc_endo_chip + .ecc_chip + .assert_equal(ctx, &result_0, &result_1)?; + + Ok(()) + }, + )?; + + config.config_range(&mut layouter)?; + + Ok(()) + } + } + + #[test] + fn test_general_ecc_endo_mul_circuit() { + fn run< + C: CurveEndo, + N: FromUniformBytes<64> + WithSmallOrderMulGroup<3> + Ord, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + >() { + for window_size in 2..3 { + let aux_generator = C::random(OsRng); + + let circuit = TestEccEndoMul:: { + aux_generator, + window_size, + ..Default::default() + }; + let instance = vec![vec![]]; + mock_prover_verify(&circuit, instance); + } + } + + run::(); + run::(); + run::(); + + run::(); + run::(); + run::(); + + run::(); + run::(); + run::(); + + // run::(); + // run::(); + // run::(); } #[derive(Default, Clone, Debug)] struct TestEccBatchMul< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -861,8 +1072,12 @@ mod tests { _marker: PhantomData, } - impl - Circuit for TestEccBatchMul + impl< + C: CurveAffine, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > Circuit for TestEccBatchMul { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -891,7 +1106,12 @@ mod tests { let offset = 0; let ctx = &mut RegionCtx::new(region, offset); ecc_chip.assign_aux_generator(ctx, Value::known(self.aux_generator))?; - ecc_chip.assign_aux(ctx, self.window_size, self.number_of_pairs)?; + ecc_chip.assign_aux( + ctx, + self.window_size, + self.number_of_pairs, + C::Scalar::NUM_BITS as usize, + )?; ecc_chip.get_mul_aux(self.window_size, self.number_of_pairs)?; Ok(()) }, @@ -902,7 +1122,6 @@ mod tests { layouter.assign_region( || "region mul", |region| { - use group::ff::Field; let offset = 0; let ctx = &mut RegionCtx::new(region, offset); @@ -948,7 +1167,7 @@ mod tests { fn []() { for number_of_pairs in 5..7 { for window_size in 1..3 { - let aux_generator = <$C as PrimeCurveAffine>::Curve::random(OsRng).to_affine(); + let aux_generator = <$C as CurveAffine>::CurveExt::random(OsRng).to_affine(); let circuit = TestEccBatchMul::<$C, $N, $NUMBER_OF_LIMBS, $BIT_LEN_LIMB> { aux_generator, diff --git a/ecc/src/general_ecc/add.rs b/ecc/src/general_ecc/add.rs index 3afa9bb8..f8eac6fd 100644 --- a/ecc/src/general_ecc/add.rs +++ b/ecc/src/general_ecc/add.rs @@ -1,14 +1,15 @@ use super::AssignedPoint; use super::GeneralEccChip; use crate::halo2; -use halo2::arithmetic::{CurveAffine, FieldExt}; +use halo2::arithmetic::CurveAffine; use halo2::plonk::Error; +use integer::halo2::ff::PrimeField; use integer::maingate::RegionCtx; use integer::IntegerInstructions; impl< Emulated: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > GeneralEccChip diff --git a/ecc/src/general_ecc/mul.rs b/ecc/src/general_ecc/mul.rs index da12a01b..277a5e2d 100644 --- a/ecc/src/general_ecc/mul.rs +++ b/ecc/src/general_ecc/mul.rs @@ -1,15 +1,18 @@ use super::{AssignedPoint, GeneralEccChip}; use crate::integer::{AssignedInteger, IntegerInstructions}; use crate::maingate::{AssignedCondition, MainGateInstructions}; -use crate::{halo2, Selector, Table, Windowed}; -use group::ff::PrimeField; -use halo2::arithmetic::{CurveAffine, FieldExt}; +use crate::{halo2, AssignedDecompScalar, GeneralEndoEccChip, Selector, Table, Windowed}; +use halo2::arithmetic::CurveAffine; use halo2::plonk::Error; -use integer::maingate::RegionCtx; +use integer::halo2::curves::{CurveEndo, CurveExt}; +use integer::halo2::ff::{Field, PrimeField, WithSmallOrderMulGroup}; +use integer::maingate::{big_to_fe, RegionCtx}; +use integer::rns::{Common, Integer}; +use integer::Range; impl< Emulated: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > GeneralEccChip @@ -21,13 +24,13 @@ impl< bits: &mut Vec>, window_size: usize, ) -> Result<(), Error> { - assert_eq!(bits.len(), Emulated::ScalarExt::NUM_BITS as usize); + // assert_eq!(bits.len(), Emulated::ScalarExt::NUM_BITS as usize); // TODO: This is a tmp workaround. Instead of padding with zeros we can use a // shorter ending window. let padding_offset = (window_size - (bits.len() % window_size)) % window_size; let zeros: Vec> = (0..padding_offset) - .map(|_| self.main_gate().assign_constant(region, N::zero())) + .map(|_| self.main_gate().assign_constant(region, N::ZERO)) .collect::>()?; bits.extend(zeros); bits.reverse(); @@ -93,7 +96,7 @@ impl< } /// Scalar multiplication of a point in the EC - /// Performed with the sliding-window algorithm + /// Performed with the windowed algorithm pub fn mul( &self, region: &mut RegionCtx<'_, N>, @@ -102,26 +105,37 @@ impl< window_size: usize, ) -> Result, Error> { assert!(window_size > 0); - let aux = self.get_mul_aux(window_size, 1)?; let scalar_chip = self.scalar_field_chip(); + + // Generate a random aux point (and its final offset) for the window size and n pairs. + let aux = self.get_mul_aux(window_size, 1)?; + + // Decompose the scalar in bits and pad it to a multiple of window size let decomposed = &mut scalar_chip.decompose(region, scalar)?; self.pad(region, decomposed, window_size)?; + + // Split the decomposed scalar in windows let windowed = Self::window(decomposed.to_vec(), window_size); + + // Construct the table with the input point and the random accumulator let table = &self.make_incremental_table(region, &aux.to_add, point, window_size)?; + // First (2) iteration of double-select-add let mut acc = self.select_multi(region, &windowed.0[0], table)?; acc = self.double_n(region, &acc, window_size)?; let to_add = self.select_multi(region, &windowed.0[1], table)?; acc = self.add(region, &acc, &to_add)?; + // Rest of the iterations for selector in windowed.0.iter().skip(2) { acc = self.double_n(region, &acc, window_size - 1)?; let to_add = self.select_multi(region, selector, table)?; acc = self.ladder(region, &acc, &to_add)?; } + // Compensate the offset introduced by the random point self.add(region, &acc, &aux.to_sub) } @@ -199,3 +213,173 @@ impl< self.add(region, &acc, &aux.to_sub) } } + +impl< + Emulated: CurveEndo, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, + > GeneralEndoEccChip +{ + /// Split a scalar k in 128-bit scalars k1, k2 such that: + /// k = k1 - C::lambda * k2 + fn split_scalar( + &self, + ctx: &mut RegionCtx<'_, N>, + scalar: &AssignedInteger, + ) -> Result, Error> { + let maingate = self.ecc_chip.main_gate(); + let scalar_chip = &self.ecc_chip.scalar_field_chip; + + let pos = |neg: bool| if neg { N::ZERO } else { N::ONE }; + + // Compute decomposition + let decomposed = scalar.integer().map(|i| { + let val = big_to_fe(i.value()); + Emulated::decompose_scalar(&val) + }); + + let k1 = decomposed.map(|decomp| Emulated::Scalar::from_u128(decomp.0)); + let k1_pos = decomposed.map(|decomp| pos(decomp.1)); + let k2 = decomposed.map(|decomp| Emulated::Scalar::from_u128(decomp.2)); + let k2_pos = decomposed.map(|decomp| pos(decomp.3)); + + // Assign decomposition values + let k1 = k1.map(|v| Integer::from_fe(v, scalar_chip.rns())); + let k1 = scalar_chip.assign_integer(ctx, k1.into(), Range::Operand)?; + + let k1_pos = maingate.assign_bit(ctx, k1_pos)?; + + let k2 = k2.map(|v| Integer::from_fe(v, scalar_chip.rns())); + let k2 = scalar_chip.assign_integer(ctx, k2.into(), Range::Operand)?; + + let k2_pos = maingate.assign_bit(ctx, k2_pos)?; + + // Sanity check + // scalar.value().map(|s| dbg!(s)); + // decomposed.map(|(k1, k1_neg, k2, k2_neg)| { + // let k1 = C::Scalar::from_u128(k1); + // let k2 = C::Scalar::from_u128(k2); + // let k1_sig = sig(k1_neg); + // let k2_sig = sig(k2_neg); + // dbg!(k1, k2, k1_sig, k2_sig); + // scalar + // .value() + // .map(|k| assert_eq!(k1 * k1_sig - C::ScalarExt::ZETA * k2 * k2_sig, *k)); + // }); + + // Add decomoposition constraint + // k1 * k1_sig - C::LAMBDA * k2 * k2_sig - k = 0 + // k1_sig i {-1, 1} + // k2_sig i {-1, 1} + + let minus_one = Integer::from_fe(-Emulated::Scalar::ONE, scalar_chip.rns()); + // Constraint k = k1* k1_sig - k2* k2_sig * zeta + let minus_k1 = scalar_chip.mul_constant(ctx, &k1, &minus_one)?; + let minus_k2 = scalar_chip.mul_constant(ctx, &k2, &minus_one)?; + let signed_k1 = scalar_chip.select(ctx, &k1, &minus_k1, &k1_pos)?; + let signed_k2 = scalar_chip.select(ctx, &k2, &minus_k2, &k2_pos)?; + let minus_zeta = Integer::from_fe(-Emulated::ScalarExt::ZETA, scalar_chip.rns()); + let signed_k2_zeta = scalar_chip.mul_constant(ctx, &signed_k2, &minus_zeta)?; + + let result = scalar_chip.add(ctx, &signed_k1, &signed_k2_zeta)?; + scalar_chip.assert_equal(ctx, &result, &scalar)?; + + Ok([ + (k1.native().clone(), k1_pos.clone()), + (k2.native().clone(), k2_pos.clone()), + ]) + } + + /// Scalar multiplication of a point in the EC + /// Performed with the sliding-window algorithm + pub fn glv_mul( + &self, + ctx: &mut RegionCtx<'_, N>, + point: &AssignedPoint< + <::AffineExt as CurveAffine>::Base, + N, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >, + scalar: &AssignedInteger, + window_size: usize, + ) -> Result< + AssignedPoint< + <::AffineExt as CurveAffine>::Base, + N, + NUMBER_OF_LIMBS, + BIT_LEN_LIMB, + >, + Error, + > { + assert!(window_size > 0); + let ecc = &self.ecc_chip; + let aux = ecc.get_mul_aux(window_size, 2)?; + + // 1. Decompose scalar k -> k1, k2 + let split = self.split_scalar(ctx, scalar)?; + + // 2. Decompose scalars into AssignedCondition + let main_gate = ecc.main_gate(); + let decomp_k1 = &mut main_gate.to_bits(ctx, &split[0].0, 128usize)?; + let decomp_k2 = &mut main_gate.to_bits(ctx, &split[1].0, 128usize)?; + + // 2.1 Convert signs into Integers + let minus_point = ecc.neg(ctx, point)?; + let k1_point = ecc.select(ctx, &split[0].1, point, &minus_point)?; + let k2_point = ecc.select(ctx, &split[1].1, &minus_point, point)?; + let k2_point = ecc.endo(ctx, &k2_point)?; + + // 3. Pad to window size and chunk in windows + ecc.pad(ctx, decomp_k1, window_size)?; + ecc.pad(ctx, decomp_k2, window_size)?; + + let windowed_k1 = + GeneralEccChip::::window( + decomp_k1.to_vec(), + window_size, + ); + let windowed_k2 = + GeneralEccChip::::window( + decomp_k2.to_vec(), + window_size, + ); + let number_of_windows = windowed_k1.0.len(); + + // 4. Generate aux acc point + Generate table + let mut binary_aux = aux.to_add.clone(); + let tables: Vec> = vec![k1_point, k2_point] + .iter() + .enumerate() + .map(|(i, point)| { + let table = ecc.make_incremental_table(ctx, &binary_aux, point, window_size); + if i != 1 { + binary_aux = ecc.double(ctx, &binary_aux)?; + } + table + }) + .collect::>()?; + + // 5. Mul double-and-add algorithm + let windowed_scalars = vec![windowed_k1, windowed_k2]; + + let mut acc = ecc.select_multi(ctx, &windowed_scalars[0].0[0], &tables[0])?; + // add first contributions other point scalar + for (table, windowed) in tables.iter().skip(1).zip(windowed_scalars.iter().skip(1)) { + let selector = &windowed.0[0]; + let to_add = ecc.select_multi(ctx, selector, table)?; + acc = ecc.add(ctx, &acc, &to_add)?; + } + + for i in 1..number_of_windows { + acc = ecc.double_n(ctx, &acc, window_size)?; + for (table, windowed) in tables.iter().zip(windowed_scalars.iter()) { + let selector = &windowed.0[i]; + let to_add = ecc.select_multi(ctx, selector, table)?; + acc = ecc.add(ctx, &acc, &to_add)?; + } + } + ecc.add(ctx, &acc, &aux.to_sub) + } +} diff --git a/ecc/src/lib.rs b/ecc/src/lib.rs index 2f81443b..f6abb6a3 100644 --- a/ecc/src/lib.rs +++ b/ecc/src/lib.rs @@ -13,31 +13,40 @@ pub mod general_ecc; pub use integer; pub use integer::halo2; +use integer::halo2::ff::PrimeField; pub use integer::maingate; #[cfg(test)] use halo2::halo2curves as curves; +use integer::maingate::AssignedValue; -use crate::halo2::arithmetic::{CurveAffine, FieldExt}; +use crate::halo2::arithmetic::CurveAffine; use crate::integer::chip::IntegerConfig; use crate::integer::rns::{Integer, Rns}; use crate::integer::AssignedInteger; use crate::maingate::{big_to_fe, AssignedCondition, MainGateConfig, RangeConfig}; -use group::Curve; +use integer::halo2::group::Curve; use num_bigint::BigUint as big_uint; use num_traits::One; use std::fmt; use std::rc::Rc; +/// Assigned decomposition of a scalar of field F into 2: 128 bit vals + sign_flag (0 pos, 1 neg) +type AssignedDecompScalar = [(AssignedValue, AssignedCondition); 2]; + /// Represent a Point in affine coordinates #[derive(Clone, Debug)] -pub struct Point -{ +pub struct Point< + W: PrimeField, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { x: Integer, y: Integer, } -impl +impl Point { /// Returns `Point` form a point in a EC with W as its base field @@ -77,8 +86,8 @@ impl { @@ -86,8 +95,8 @@ pub struct AssignedPoint< pub(crate) y: AssignedInteger, } -impl fmt::Debug - for AssignedPoint +impl + fmt::Debug for AssignedPoint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("AssignedPoint") @@ -98,7 +107,7 @@ impl +impl AssignedPoint { /// Returns a new `AssignedPoint` given its coordinates as `AssignedInteger` @@ -149,14 +158,18 @@ impl EccConfig { /// /// Computes AuxFin from AuxInit for batch multiplication /// see https://hackmd.io/ncuKqRXzR-Cw-Au2fGzsMg?view -fn make_mul_aux(aux_to_add: C, window_size: usize, number_of_pairs: usize) -> C { +fn make_mul_aux( + aux_to_add: C, + window_size: usize, + number_of_pairs: usize, + n_bits: usize, +) -> C { assert!(window_size > 0); assert!(number_of_pairs > 0); - use group::ff::PrimeField; + assert!((n_bits == 128) | (n_bits == C::Scalar::NUM_BITS as usize)); - let n = C::Scalar::NUM_BITS as usize; - let mut number_of_selectors = n / window_size; - if n % window_size != 0 { + let mut number_of_selectors = n_bits / window_size; + if n_bits % window_size != 0 { number_of_selectors += 1; } let mut k0 = big_uint::one(); @@ -176,9 +189,9 @@ fn make_mul_aux(aux_to_add: C, window_size: usize, number_of_pai /// Allows to select values of precomputed table in efficient multiplication /// algorithm #[derive(Default)] -pub(crate) struct Selector(Vec>); +pub(crate) struct Selector(Vec>); -impl fmt::Debug for Selector { +impl fmt::Debug for Selector { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Selector"); for (i, bit) in self.0.iter().enumerate() { @@ -191,9 +204,9 @@ impl fmt::Debug for Selector { /// Vector of `Selectors` which represent the binary representation of a scalar /// split in window sized selectors. -pub(crate) struct Windowed(Vec>); +pub(crate) struct Windowed(Vec>); -impl fmt::Debug for Windowed { +impl fmt::Debug for Windowed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Window"); for (i, selector) in self.0.iter().enumerate() { @@ -208,14 +221,14 @@ impl fmt::Debug for Windowed { /// Table of precomputed values for efficient multiplication algorithm. pub(crate) struct Table< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >(pub(crate) Vec>); -impl fmt::Debug - for Table +impl + fmt::Debug for Table { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Table"); @@ -232,13 +245,14 @@ impl { +struct MulAux +{ to_add: AssignedPoint, to_sub: AssignedPoint, } /// Constructs `MulAux` -impl +impl MulAux { fn new( diff --git a/ecdsa/Cargo.toml b/ecdsa/Cargo.toml index 7a2b2bff..a1711360 100644 --- a/ecdsa/Cargo.toml +++ b/ecdsa/Cargo.toml @@ -9,7 +9,6 @@ num-bigint = { version = "0.4", features = ["rand"] } num-integer = "0.1" num-traits = "0.2" rand = "0.8" -group = "0.12" subtle = { version = "2.3", default-features = false } [dev-dependencies] diff --git a/ecdsa/src/ecdsa.rs b/ecdsa/src/ecdsa.rs index c93601fb..f9b6d340 100644 --- a/ecdsa/src/ecdsa.rs +++ b/ecdsa/src/ecdsa.rs @@ -2,10 +2,10 @@ use super::integer::{IntegerChip, IntegerConfig}; use crate::halo2; use crate::integer; use crate::maingate; -use ecc::maingate::MainGateInstructions; +use ecc::halo2::ff::PrimeField; use ecc::maingate::RegionCtx; use ecc::{AssignedPoint, EccConfig, GeneralEccChip}; -use halo2::arithmetic::{CurveAffine, FieldExt}; +use halo2::arithmetic::CurveAffine; use halo2::{circuit::Value, plonk::Error}; use integer::rns::Integer; use integer::{AssignedInteger, IntegerInstructions}; @@ -36,8 +36,8 @@ impl EcdsaConfig { #[derive(Clone, Debug)] pub struct EcdsaSig< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -46,8 +46,8 @@ pub struct EcdsaSig< } pub struct AssignedEcdsaSig< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -56,8 +56,8 @@ pub struct AssignedEcdsaSig< } pub struct AssignedPublicKey< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -66,12 +66,12 @@ pub struct AssignedPublicKey< pub struct EcdsaChip< E: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >(GeneralEccChip); -impl +impl EcdsaChip { pub fn new(ecc_chip: GeneralEccChip) -> Self { @@ -89,7 +89,7 @@ impl +impl EcdsaChip { pub fn verify( @@ -143,16 +143,18 @@ mod tests { use crate::halo2; use crate::integer; use crate::maingate; + use ecc::halo2::ff::FromUniformBytes; + use ecc::halo2::ff::WithSmallOrderMulGroup; + use ecc::halo2::group::Curve; + use ecc::halo2::group::Group; use ecc::integer::Range; use ecc::maingate::big_to_fe; use ecc::maingate::fe_to_big; use ecc::maingate::RegionCtx; use ecc::{EccConfig, GeneralEccChip}; - use group::ff::Field; - use group::{Curve, Group}; use halo2::arithmetic::CurveAffine; - use halo2::arithmetic::FieldExt; use halo2::circuit::{Layouter, SimpleFloorPlanner, Value}; + use halo2::ff::{Field, PrimeField}; use halo2::plonk::{Circuit, ConstraintSystem, Error}; use integer::IntegerInstructions; use maingate::mock_prover_verify; @@ -170,7 +172,7 @@ mod tests { } impl TestCircuitEcdsaVerifyConfig { - pub fn new(meta: &mut ConstraintSystem) -> Self { + pub fn new(meta: &mut ConstraintSystem) -> Self { let (rns_base, rns_scalar) = GeneralEccChip::::rns(); let main_gate_config = MainGate::::configure(meta); @@ -195,7 +197,7 @@ mod tests { EccConfig::new(self.range_config.clone(), self.main_gate_config.clone()) } - pub fn config_range( + pub fn config_range( &self, layouter: &mut impl Layouter, ) -> Result<(), Error> { @@ -207,7 +209,7 @@ mod tests { } #[derive(Default, Clone)] - struct TestCircuitEcdsaVerify { + struct TestCircuitEcdsaVerify { public_key: Value, signature: Value<(E::Scalar, E::Scalar)>, msg_hash: Value, @@ -217,7 +219,7 @@ mod tests { _marker: PhantomData, } - impl Circuit for TestCircuitEcdsaVerify { + impl Circuit for TestCircuitEcdsaVerify { type Config = TestCircuitEcdsaVerifyConfig; type FloorPlanner = SimpleFloorPlanner; @@ -245,7 +247,12 @@ mod tests { let ctx = &mut RegionCtx::new(region, offset); ecc_chip.assign_aux_generator(ctx, Value::known(self.aux_generator))?; - ecc_chip.assign_aux(ctx, self.window_size, 2)?; + ecc_chip.assign_aux( + ctx, + self.window_size, + 2, + E::ScalarExt::NUM_BITS as usize, + )?; Ok(()) }, )?; @@ -296,7 +303,7 @@ mod tests { big_to_fe(x_big) } - fn run() { + fn run + FromUniformBytes<64> + Ord>() { let g = C::generator(); // Generate a key pair diff --git a/halo2wrong/Cargo.toml b/halo2wrong/Cargo.toml index f3bd12ef..9a53d4dc 100644 --- a/halo2wrong/Cargo.toml +++ b/halo2wrong/Cargo.toml @@ -9,7 +9,6 @@ num-bigint = { version = "0.4", features = ["rand"] } num-integer = "0.1" num-traits = "0.2" halo2 = { package = "halo2_proofs", git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v2023_02_02" } -group = "0.12" [dev-dependencies] rand = "0.8" diff --git a/halo2wrong/src/lib.rs b/halo2wrong/src/lib.rs index 7d3ddecb..b5578adf 100644 --- a/halo2wrong/src/lib.rs +++ b/halo2wrong/src/lib.rs @@ -1,6 +1,6 @@ use halo2::{ - arithmetic::FieldExt, circuit::{AssignedCell, Cell, Region, Value}, + ff::PrimeField, plonk::{Advice, Column, Error, Fixed, Selector}, }; @@ -9,12 +9,12 @@ pub use halo2; pub use halo2::halo2curves as curves; #[derive(Debug)] -pub struct RegionCtx<'a, F: FieldExt> { +pub struct RegionCtx<'a, F: PrimeField> { region: Region<'a, F>, offset: usize, } -impl<'a, F: FieldExt> RegionCtx<'a, F> { +impl<'a, F: PrimeField> RegionCtx<'a, F> { pub fn new(region: Region<'a, F>, offset: usize) -> RegionCtx<'a, F> { RegionCtx { region, offset } } diff --git a/halo2wrong/src/utils.rs b/halo2wrong/src/utils.rs index d0401ffe..408f2806 100644 --- a/halo2wrong/src/utils.rs +++ b/halo2wrong/src/utils.rs @@ -1,5 +1,4 @@ use crate::halo2::{ - arithmetic::FieldExt, circuit::Value, dev::MockProver, plonk::{ @@ -7,7 +6,10 @@ use crate::halo2::{ FloorPlanner, Instance, Selector, }, }; -use halo2::plonk::Challenge; +use halo2::{ + ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup}, + plonk::Challenge, +}; use num_bigint::BigUint as big_uint; use num_traits::{Num, One, Zero}; use std::{ @@ -15,29 +17,29 @@ use std::{ ops::{RangeInclusive, Shl}, }; -pub fn modulus() -> big_uint { +pub fn modulus() -> big_uint { big_uint::from_str_radix(&F::MODULUS[2..], 16).unwrap() } -pub fn power_of_two(n: usize) -> F { +pub fn power_of_two(n: usize) -> F { big_to_fe(big_uint::one() << n) } -pub fn big_to_fe(e: big_uint) -> F { +pub fn big_to_fe(e: big_uint) -> F { let modulus = modulus::(); let e = e % modulus; F::from_str_vartime(&e.to_str_radix(10)[..]).unwrap() } -pub fn fe_to_big(fe: F) -> big_uint { +pub fn fe_to_big(fe: F) -> big_uint { big_uint::from_bytes_le(fe.to_repr().as_ref()) } -pub fn decompose(e: F, number_of_limbs: usize, bit_len: usize) -> Vec { +pub fn decompose(e: F, number_of_limbs: usize, bit_len: usize) -> Vec { decompose_big(fe_to_big(e), number_of_limbs, bit_len) } -pub fn decompose_big(e: big_uint, number_of_limbs: usize, bit_len: usize) -> Vec { +pub fn decompose_big(e: big_uint, number_of_limbs: usize, bit_len: usize) -> Vec { let mut e = e; let mask = big_uint::from(1usize).shl(bit_len) - 1usize; let limbs: Vec = (0..number_of_limbs) @@ -63,7 +65,14 @@ pub fn compose(input: Vec, bit_len: usize) -> big_uint { .fold(big_uint::zero(), |acc, val| (acc << bit_len) + val) } -pub fn mock_prover_verify>(circuit: &C, instance: Vec>) { + +pub fn mock_prover_verify< + F: WithSmallOrderMulGroup<3> + FromUniformBytes<64> + Ord, + C: Circuit, +>( + circuit: &C, + instance: Vec>, +) { let dimension = DimensionMeasurement::measure(circuit).unwrap(); let prover = MockProver::run(dimension.k(), circuit, instance) .unwrap_or_else(|err| panic!("{:#?}", err)); @@ -118,7 +127,7 @@ impl DimensionMeasurement { } } - pub fn measure>(circuit: &C) -> Result { + pub fn measure>(circuit: &C) -> Result { let mut cs = ConstraintSystem::default(); let config = C::configure(&mut cs); let mut measurement = Self::default(); @@ -132,7 +141,7 @@ impl DimensionMeasurement { } } -impl Assignment for DimensionMeasurement { +impl Assignment for DimensionMeasurement { fn enter_region(&mut self, _: N) where NR: Into, @@ -140,6 +149,13 @@ impl Assignment for DimensionMeasurement { { } + fn annotate_column(&mut self, _annotation: A, _column: Column) + where + A: FnOnce() -> AR, + AR: Into, + { + } + fn exit_region(&mut self) {} fn get_challenge(&self, _challenge: Challenge) -> Value { @@ -160,14 +176,6 @@ impl Assignment for DimensionMeasurement { Ok(Value::unknown()) } - fn annotate_column(&mut self, _annotation: A, _column: Column) - where - A: FnOnce() -> AR, - AR: Into, - { - // Do nothing. - } - fn assign_advice( &mut self, _: A, @@ -237,7 +245,7 @@ impl Assignment for DimensionMeasurement { #[test] fn test_round_trip() { use crate::curves::pasta::Fp; - use group::ff::Field as _; + use halo2::ff::Field as _; use num_bigint::RandomBits; use rand::Rng; use rand_core::OsRng; @@ -286,7 +294,7 @@ fn test_dimension_measurement() { #[derive(Default)] struct TestCircuit(PhantomData); - impl Circuit for TestCircuit { + impl Circuit for TestCircuit { type Config = (Column, Column, [Column; 2]); type FloorPlanner = V1; @@ -311,7 +319,7 @@ fn test_dimension_measurement() { || "", |mut region| { for i in 0..15 { - region.assign_fixed(|| "", f0, i, || Value::known(F::zero()))?; + region.assign_fixed(|| "", f0, i, || Value::known(F::ZERO))?; } Ok(()) }, @@ -320,7 +328,7 @@ fn test_dimension_measurement() { || "", |mut region| { for i in 0..10 { - region.assign_advice(|| "", a0, i, || Value::known(F::zero()))?; + region.assign_advice(|| "", a0, i, || Value::known(F::ZERO))?; } Ok(()) }, @@ -329,7 +337,7 @@ fn test_dimension_measurement() { || "", |mut region| { for i in 0..20 { - region.assign_advice(|| "", a1, i, || Value::known(F::zero()))?; + region.assign_advice(|| "", a1, i, || Value::known(F::ZERO))?; } Ok(()) }, @@ -341,7 +349,7 @@ fn test_dimension_measurement() { for i in 0..20 { cell = Some( region - .assign_advice(|| "", a0, i, || Value::known(F::zero()))? + .assign_advice(|| "", a0, i, || Value::known(F::ZERO))? .cell(), ); } diff --git a/integer/Cargo.toml b/integer/Cargo.toml index 03dd971c..428304b4 100644 --- a/integer/Cargo.toml +++ b/integer/Cargo.toml @@ -10,7 +10,6 @@ num-bigint = { version = "0.4", features = ["rand"] } num-integer = "0.1" num-traits = "0.2" rand = "0.8" -group = "0.12" subtle = { version = "2.3", default-features = false } [dev-dependencies] diff --git a/integer/src/chip.rs b/integer/src/chip.rs index 666bfa7e..d341bf5c 100644 --- a/integer/src/chip.rs +++ b/integer/src/chip.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use super::{AssignedInteger, AssignedLimb, UnassignedInteger}; use crate::instructions::{IntegerInstructions, Range}; use crate::rns::{Common, Integer, Rns}; -use halo2::arithmetic::FieldExt; use halo2::plonk::Error; +use maingate::halo2::ff::PrimeField; use maingate::{halo2, AssignedCondition, AssignedValue, MainGateInstructions, RegionCtx}; use maingate::{MainGate, MainGateConfig}; use maingate::{RangeChip, RangeConfig}; @@ -43,8 +43,8 @@ impl IntegerConfig { /// Chip for integer instructions #[derive(Clone, Debug)] pub struct IntegerChip< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -56,7 +56,7 @@ pub struct IntegerChip< rns: Rc>, } -impl +impl IntegerChip { fn sublimb_bit_len() -> usize { @@ -76,11 +76,11 @@ impl +impl IntegerInstructions for IntegerChip { - fn reduce_external( + fn reduce_external( &self, ctx: &mut RegionCtx<'_, N>, // TODO: external integer might have different parameter settings @@ -519,7 +519,7 @@ impl +impl IntegerChip { /// Create new ['IntegerChip'] with the configuration and a shared [`Rns`] @@ -551,7 +551,7 @@ impl( + fn rns( ) -> Rns { Rns::::construct() } - fn setup( + fn setup( ) -> (Rns, u32) { let rns = rns(); let k: u32 = (rns.bit_len_lookup + 1) as u32; (rns, k) } - impl + impl From> for UnassignedInteger { @@ -587,11 +587,11 @@ mod tests { } } - pub(crate) struct TestRNS { + pub(crate) struct TestRNS { rns: Rc>, } - impl TestRNS { + impl TestRNS { pub(crate) fn rand_in_field(&self) -> Integer { Integer::from_fe(W::random(OsRng), Rc::clone(&self.rns)) } @@ -673,7 +673,7 @@ mod tests { } impl TestCircuitConfig { - fn new( + fn new( meta: &mut ConstraintSystem, ) -> Self { let main_gate_config = MainGate::::configure(meta); @@ -701,7 +701,10 @@ mod tests { } } - fn config_range(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + fn config_range( + &self, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { let range_chip = RangeChip::::new(self.range_config.clone()); range_chip.load_table(layouter)?; @@ -714,11 +717,11 @@ mod tests { #[derive(Clone, Debug)] - struct $circuit_name { + struct $circuit_name { rns: Rc>, } - impl $circuit_name { + impl $circuit_name { fn integer_chip(&self, config:TestCircuitConfig) -> IntegerChip{ IntegerChip::::new(config.integer_chip_config(), Rc::clone(&self.rns)) } @@ -729,7 +732,7 @@ mod tests { } - impl Circuit for $circuit_name { + impl Circuit for $circuit_name { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1367,7 +1370,7 @@ mod tests { let a = t.rand_in_remainder_range().into(); let b = t.rand_in_remainder_range().into(); - let cond = N::zero(); + let cond = N::ZERO; let cond = Value::known(cond); let a = integer_chip.assign_integer(ctx, a, Range::Remainder)?; @@ -1383,7 +1386,7 @@ mod tests { let a = t.rand_in_remainder_range().into(); let b = t.rand_in_remainder_range().into(); - let cond = N::one(); + let cond = N::ONE; let cond = Value::known(cond); let a = integer_chip.assign_integer(ctx, a, Range::Remainder)?; @@ -1399,7 +1402,7 @@ mod tests { let a = t.rand_in_remainder_range().into(); let b = t.rand_in_remainder_range(); - let cond = N::zero(); + let cond = N::ZERO; let cond = Value::known(cond); let a = integer_chip.assign_integer(ctx, a, Range::Remainder)?; @@ -1415,7 +1418,7 @@ mod tests { let a = t.rand_in_remainder_range().into(); let b = t.rand_in_remainder_range(); - let cond = N::one(); + let cond = N::ONE; let cond = Value::known(cond); let a = integer_chip.assign_integer(ctx, a, Range::Remainder)?; @@ -1460,7 +1463,7 @@ mod tests { ); assert_eq!(expected.len(), decomposed.len()); for (c, expected) in decomposed.iter().zip(expected.into_iter()) { - if expected != W::zero() { + if expected != W::ZERO { main_gate.assert_one(ctx, c)?; } else { main_gate.assert_zero(ctx, c)?; diff --git a/integer/src/chip/add.rs b/integer/src/chip/add.rs index 3fb3e5cd..10e859f6 100644 --- a/integer/src/chip/add.rs +++ b/integer/src/chip/add.rs @@ -1,12 +1,12 @@ use crate::chip::IntegerChip; use crate::rns::Integer; -use crate::{AssignedInteger, AssignedLimb, Common, FieldExt}; +use crate::{AssignedInteger, AssignedLimb, Common, PrimeField}; use halo2::plonk::Error; use maingate::{fe_to_big, halo2, MainGateInstructions, RegionCtx, Term}; use num_bigint::BigUint as big_uint; use std::rc::Rc; -impl +impl IntegerChip { pub(super) fn add_generic( @@ -56,7 +56,7 @@ impl +impl IntegerChip { pub(super) fn assert_in_field_generic( @@ -35,13 +35,13 @@ impl>, Error>>()?; let left_shifter = self.rns.left_shifter(1); - let one = N::one(); + let one = N::ONE; // Witness layout: // | A | B | C | D | diff --git a/integer/src/chip/assert_not_zero.rs b/integer/src/chip/assert_not_zero.rs index 2a596a6b..68042303 100644 --- a/integer/src/chip/assert_not_zero.rs +++ b/integer/src/chip/assert_not_zero.rs @@ -1,11 +1,11 @@ use super::IntegerChip; -use crate::{AssignedInteger, FieldExt}; +use crate::{AssignedInteger, PrimeField}; use halo2::plonk::Error; use maingate::{halo2, CombinationOptionCommon, MainGateInstructions, RegionCtx, Term}; use num_bigint::BigUint as big_uint; use std::convert::TryInto; -impl +impl IntegerChip { pub(super) fn assert_not_zero_generic( @@ -14,7 +14,7 @@ impl, ) -> Result<(), Error> { let main_gate = self.main_gate(); - let one = N::one(); + let one = N::ONE; // Reduce result (r) is restricted to be less than 1 << // wrong_modulus_bit_lenght, so we only need to assert r <> 0 and r <> diff --git a/integer/src/chip/assert_zero.rs b/integer/src/chip/assert_zero.rs index 81233672..dcc95c57 100644 --- a/integer/src/chip/assert_zero.rs +++ b/integer/src/chip/assert_zero.rs @@ -1,11 +1,11 @@ use super::IntegerChip; use crate::rns::MaybeReduced; -use crate::{AssignedInteger, FieldExt}; +use crate::{AssignedInteger, PrimeField}; use halo2::plonk::Error; use maingate::{halo2, AssignedValue, MainGateInstructions, RangeInstructions, RegionCtx, Term}; -impl +impl IntegerChip { pub(super) fn assert_zero_generic( @@ -14,7 +14,7 @@ impl, ) -> Result<(), Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let witness: MaybeReduced = a.integer().as_ref().map(|a_int| a_int.reduce()).into(); diff --git a/integer/src/chip/assign.rs b/integer/src/chip/assign.rs index f3f2c72c..2a42c348 100644 --- a/integer/src/chip/assign.rs +++ b/integer/src/chip/assign.rs @@ -1,14 +1,14 @@ use super::{IntegerChip, Range}; use crate::rns::{Common, Integer}; use crate::{AssignedInteger, AssignedLimb, UnassignedInteger}; -use halo2::arithmetic::FieldExt; use halo2::plonk::Error; +use maingate::halo2::ff::PrimeField; use maingate::{fe_to_big, halo2, MainGateInstructions, RangeInstructions, RegionCtx, Term}; use num_bigint::BigUint as big_uint; use num_traits::One; use std::rc::Rc; -impl +impl IntegerChip { pub(super) fn assign_integer_generic( @@ -85,7 +85,7 @@ impl +impl IntegerChip { pub(super) fn div_generic( @@ -40,7 +40,7 @@ impl +impl IntegerChip { pub(super) fn invert_generic( @@ -51,19 +51,19 @@ impl +impl IntegerChip { pub(super) fn constrain_binary_crt( @@ -18,7 +18,7 @@ impl>, ) -> Result<(), Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); // Constrain residues let lsh_one = self.rns.left_shifter(1); @@ -72,7 +72,7 @@ impl, ) -> Result, Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let negative_wrong_modulus = self.rns.negative_wrong_modulus_decomposed; @@ -200,7 +200,7 @@ impl, ) -> Result, Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let negative_wrong_modulus = self.rns.negative_wrong_modulus_decomposed; @@ -274,7 +274,7 @@ impl, ) -> Result<(), Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let negative_wrong_modulus = self.rns.negative_wrong_modulus_decomposed; diff --git a/integer/src/chip/reduce.rs b/integer/src/chip/reduce.rs index 2718535a..2bf39930 100644 --- a/integer/src/chip/reduce.rs +++ b/integer/src/chip/reduce.rs @@ -1,10 +1,10 @@ use super::{IntegerChip, IntegerInstructions, Range}; use crate::rns::MaybeReduced; -use crate::{AssignedInteger, FieldExt}; +use crate::{AssignedInteger, PrimeField}; use halo2::plonk::Error; use maingate::{halo2, AssignedValue, MainGateInstructions, RangeInstructions, RegionCtx, Term}; -impl +impl IntegerChip { /// Reduces an [`AssignedInteger`] if any of its limbs values is greater @@ -79,7 +79,7 @@ impl, ) -> Result, Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let witness: MaybeReduced = a.integer().as_ref().map(|a_int| a_int.reduce()).into(); diff --git a/integer/src/chip/square.rs b/integer/src/chip/square.rs index 73d6a7a4..9a6f2c57 100644 --- a/integer/src/chip/square.rs +++ b/integer/src/chip/square.rs @@ -1,12 +1,12 @@ use super::{IntegerChip, IntegerInstructions, Range}; -use crate::{rns::MaybeReduced, AssignedInteger, FieldExt}; +use crate::{rns::MaybeReduced, AssignedInteger, PrimeField}; use halo2::{arithmetic::Field, plonk::Error}; use maingate::{ halo2, AssignedValue, CombinationOptionCommon, MainGateInstructions, RangeInstructions, RegionCtx, Term, }; -impl +impl IntegerChip { #[allow(clippy::needless_range_loop)] @@ -16,7 +16,7 @@ impl, ) -> Result, Error> { let main_gate = self.main_gate(); - let (zero, one) = (N::zero(), N::one()); + let (zero, one) = (N::ZERO, N::ONE); let negative_wrong_modulus = self.rns.negative_wrong_modulus_decomposed; diff --git a/integer/src/instructions.rs b/integer/src/instructions.rs index f50cb951..910a4a5f 100644 --- a/integer/src/instructions.rs +++ b/integer/src/instructions.rs @@ -1,8 +1,8 @@ use super::{AssignedInteger, UnassignedInteger}; use crate::maingate::{halo2, AssignedCondition, RegionCtx}; use crate::rns::Integer; -use halo2::arithmetic::FieldExt; use halo2::plonk::Error; +use maingate::halo2::ff::PrimeField; /// Signals the range mode that should be applied while assigning a new /// [`Integer`] @@ -20,8 +20,8 @@ pub enum Range { /// Common functionality for non native integer constraints pub trait IntegerInstructions< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > @@ -289,7 +289,7 @@ pub trait IntegerInstructions< /// Tries to apply reduction to an [`AssignedInteger`] that is not in this /// wrong field - fn reduce_external( + fn reduce_external( &self, ctx: &mut RegionCtx<'_, N>, a: &AssignedInteger, diff --git a/integer/src/lib.rs b/integer/src/lib.rs index f5dba271..5a23ea89 100644 --- a/integer/src/lib.rs +++ b/integer/src/lib.rs @@ -5,7 +5,8 @@ #![deny(missing_docs)] use crate::rns::{Common, Integer, Limb}; -use halo2::{arithmetic::FieldExt, circuit::Value}; +use halo2::circuit::Value; +use maingate::halo2::ff::PrimeField; use maingate::{big_to_fe, compose, fe_to_big, AssignedValue}; use num_bigint::BigUint as big_uint; use rns::Rns; @@ -33,7 +34,7 @@ pub const NUMBER_OF_LOOKUP_LIMBS: usize = 4; /// AssignedLimb is a limb of an non native integer #[derive(Debug, Clone)] -pub struct AssignedLimb { +pub struct AssignedLimb { // Witness value value: AssignedValue, // Maximum value to track overflow and reduction flow @@ -41,32 +42,32 @@ pub struct AssignedLimb { } /// `AssignedLimb` can be also represented as `AssignedValue` -impl From> for AssignedValue { +impl From> for AssignedValue { fn from(limb: AssignedLimb) -> Self { limb.value } } /// `AssignedLimb` can be also represented as `AssignedValue` -impl From<&AssignedLimb> for AssignedValue { +impl From<&AssignedLimb> for AssignedValue { fn from(limb: &AssignedLimb) -> Self { limb.value.clone() } } -impl AsRef> for AssignedLimb { +impl AsRef> for AssignedLimb { fn as_ref(&self) -> &AssignedValue { &self.value } } -impl AssignedLimb { +impl AssignedLimb { fn value(&self) -> Value { self.value.value().cloned() } } -impl AssignedLimb { +impl AssignedLimb { /// Given an assigned value and expected maximum value constructs new /// `AssignedLimb` fn from(value: AssignedValue, max_val: big_uint) -> Self { @@ -111,13 +112,13 @@ impl AssignedLimb { /// Witness integer that is about to be assigned. #[derive(Debug, Clone)] pub struct UnassignedInteger< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >(Value>); -impl +impl From>> for UnassignedInteger { @@ -129,8 +130,8 @@ impl { @@ -142,7 +143,7 @@ pub struct AssignedInteger< rns: Rc>, } -impl +impl AssignedInteger { /// Creates a new [`AssignedInteger`]. diff --git a/integer/src/rns.rs b/integer/src/rns.rs index 62a9b976..7df8dcf9 100644 --- a/integer/src/rns.rs +++ b/integer/src/rns.rs @@ -1,5 +1,6 @@ use crate::NUMBER_OF_LOOKUP_LIMBS; -use halo2::{arithmetic::FieldExt, circuit::Value}; +use halo2::circuit::Value; +use maingate::halo2::ff::PrimeField; use maingate::{big_to_fe, compose, decompose_big, fe_to_big, halo2, modulus}; use num_bigint::BigUint as big_uint; use num_integer::Integer as _; @@ -9,7 +10,7 @@ use std::marker::PhantomData; use std::rc::Rc; /// Common interface for [`Limb`] and [`Integer`] -pub trait Common { +pub trait Common { /// Returns the represented value fn value(&self) -> big_uint; @@ -25,7 +26,7 @@ pub trait Common { } } -impl +impl From> for big_uint { fn from(el: Integer) -> Self { @@ -41,7 +42,7 @@ fn bool_to_big(truth: bool) -> big_uint { } } -impl From> for big_uint { +impl From> for big_uint { fn from(limb: Limb) -> Self { limb.value() } @@ -51,8 +52,8 @@ impl From> for big_uint { // multiplication gate. #[derive(Clone)] pub(crate) struct ReductionWitness< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -64,13 +65,13 @@ pub(crate) struct ReductionWitness< // Wrapper for reduction witnesses pub(crate) struct MaybeReduced< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >(Value>); -impl +impl From>> for MaybeReduced { @@ -79,7 +80,7 @@ impl +impl MaybeReduced { /// Returns the quotient value as [`Integer`]. @@ -129,8 +130,12 @@ impl -{ +pub enum Quotient< + W: PrimeField, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { /// Single limb quotient Short(N), /// Integer quotient @@ -141,8 +146,8 @@ pub enum Quotient { @@ -157,7 +162,12 @@ pub(crate) struct ComparisionWitness< /// Contains all the necessary values to carry out operations such as /// multiplication and reduction in this representation. #[derive(Debug, Clone)] -pub struct Rns { +pub struct Rns< + W: PrimeField, + N: PrimeField, + const NUMBER_OF_LIMBS: usize, + const BIT_LEN_LIMB: usize, +> { /// Bit lenght of sublimbs that is subject to to lookup check pub bit_len_lookup: usize, @@ -217,7 +227,7 @@ pub struct Rns, } -impl +impl Rns { /// Calculates [`Rns`] `base_aux`. @@ -620,33 +630,33 @@ impl(F); +pub struct Limb(F); -impl Common for Limb { +impl Common for Limb { fn value(&self) -> big_uint { fe_to_big(self.0) } } -impl Default for Limb { +impl Default for Limb { fn default() -> Self { - Limb(F::zero()) + Limb(F::ZERO) } } -impl From for Limb { +impl From for Limb { fn from(e: big_uint) -> Self { Self(big_to_fe(e)) } } -impl From<&str> for Limb { +impl From<&str> for Limb { fn from(e: &str) -> Self { Self(big_to_fe(big_uint::from_str_radix(e, 16).unwrap())) } } -impl Limb { +impl Limb { pub(crate) fn new(value: F) -> Self { Limb(value) } @@ -662,8 +672,8 @@ impl Limb { /// native field plus a reference to the [`Rns`] used. #[derive(Clone)] pub struct Integer< - W: FieldExt, - N: FieldExt, + W: PrimeField, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > { @@ -671,8 +681,8 @@ pub struct Integer< rns: Rc>, } -impl fmt::Debug - for Integer +impl + fmt::Debug for Integer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let value = self.value(); @@ -687,8 +697,8 @@ impl Common - for Integer +impl + Common for Integer { fn value(&self) -> big_uint { let limb_values = self.limbs.iter().map(|limb| limb.value()).collect(); @@ -696,7 +706,7 @@ impl +impl Integer { /// Creates a new integer from a vector of limbs and reference to the used @@ -783,7 +793,7 @@ impl = vec![N::zero(); l]; + let mut t: Vec = vec![N::ZERO; l]; for k in 0..l { for i in 0..=k { let j = k - i; @@ -825,7 +835,7 @@ impl = vec![N::zero(); l]; + let mut intermediate: Vec = vec![N::ZERO; l]; for k in 0..l { for i in 0..=k { let j = k - i; @@ -881,7 +891,7 @@ impl { +pub enum Term<'a, F: PrimeField> { /// Assigned value and fixed scalar Assigned(&'a AssignedValue, F), /// Unassigned witness and fixed scalar @@ -36,13 +37,13 @@ pub enum Term<'a, F: FieldExt> { Zero, } -impl<'a, F: FieldExt> Term<'a, F> { +impl<'a, F: PrimeField> Term<'a, F> { pub(crate) const fn is_zero(&self) -> bool { matches!(self, Term::Zero) } } -impl<'a, F: FieldExt> std::fmt::Debug for Term<'a, F> { +impl<'a, F: PrimeField> std::fmt::Debug for Term<'a, F> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Assigned(coeff, base) => f @@ -61,37 +62,37 @@ impl<'a, F: FieldExt> std::fmt::Debug for Term<'a, F> { } } -impl<'a, F: FieldExt> Term<'a, F> { +impl<'a, F: PrimeField> Term<'a, F> { /// Wrap an assigned value that is about to be multiplied by other term pub fn assigned_to_mul(e: &'a AssignedValue) -> Self { - Term::Assigned(e, F::zero()) + Term::Assigned(e, F::ZERO) } /// Wrap an assigned value that is about to be added to the other terms pub fn assigned_to_add(e: &'a AssignedValue) -> Self { - Term::Assigned(e, F::one()) + Term::Assigned(e, F::ONE) } /// Wrap an assigned value that is about to be subtracted from the other /// terms pub fn assigned_to_sub(e: &'a AssignedValue) -> Self { - Term::Assigned(e, -F::one()) + Term::Assigned(e, -F::ONE) } /// Wrap an unassigned value that is about to be multiplied by other term pub fn unassigned_to_mul(e: Value) -> Self { - Term::Unassigned(e, F::zero()) + Term::Unassigned(e, F::ZERO) } /// Wrap an unassigned value that is about to be added to the other terms pub fn unassigned_to_add(e: Value) -> Self { - Term::Unassigned(e, F::one()) + Term::Unassigned(e, F::ONE) } /// Wrap an unassigned value that is about to be subtracted from the other /// terms pub fn unassigned_to_sub(e: Value) -> Self { - Term::Unassigned(e, -F::one()) + Term::Unassigned(e, -F::ONE) } /// Retuns the witness part of this term @@ -99,7 +100,7 @@ impl<'a, F: FieldExt> Term<'a, F> { match self { Self::Assigned(assigned, _) => assigned.value().copied(), Self::Unassigned(unassigned, _) => *unassigned, - Self::Zero => Value::known(F::zero()), + Self::Zero => Value::known(F::ZERO), } } @@ -108,7 +109,7 @@ impl<'a, F: FieldExt> Term<'a, F> { match self { Self::Assigned(_, base) => *base, Self::Unassigned(_, base) => *base, - Self::Zero => F::zero(), + Self::Zero => F::ZERO, } } @@ -128,7 +129,7 @@ impl<'a, F: FieldExt> Term<'a, F> { /// when it has one multiplication gate one addition gate and one further /// rotation gate. #[derive(Clone, Debug)] -pub enum CombinationOptionCommon { +pub enum CombinationOptionCommon { /// Opens only single multiplication gate OneLinerMul, /// All multiplications gates are closed @@ -148,7 +149,7 @@ pub enum CombinationOptionCommon { /// Instructions covers many basic constaints such as assignments, logical and /// arithmetic operations. Also includes general purpose `combine` and `apply` /// functions to let user to build custom constaints using this main gate -pub trait MainGateInstructions: Chip { +pub trait MainGateInstructions: Chip { /// Options for implementors to implement some more custom functionalities type CombinationOption: From>; /// Position related customisations should be defined as ['MainGateColumn'] @@ -221,7 +222,7 @@ pub trait MainGateInstructions: Chip { Term::unassigned_to_mul(bit), Term::unassigned_to_sub(bit), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )?; @@ -245,7 +246,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_mul(bit), Term::assigned_to_sub(bit), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )?; @@ -255,6 +256,48 @@ pub trait MainGateInstructions: Chip { Ok(()) } + /// Enforces given witness value is `-1` or `1` + /// `val * val - 1 = 0` + fn assert_sign( + &self, + ctx: &mut RegionCtx<'_, F>, + sign: &AssignedValue, + ) -> Result<(), Error> { + let assigned = self.apply( + ctx, + [Term::assigned_to_mul(sign), Term::assigned_to_mul(sign)], + -F::ONE, + CombinationOptionCommon::OneLinerMul.into(), + )?; + + ctx.constrain_equal(assigned[0].cell(), assigned[1].cell())?; + + Ok(()) + } + + /// Maps an assigned sign {`-1`, `1` } to {0, 1}) + /// ` res * 2 - 1 - sign = 0 + fn sign_to_cond( + &self, + ctx: &mut RegionCtx<'_, F>, + sign: &AssignedValue, + ) -> Result, Error> { + let result = sign + .value() + .map(|v| if *v == F::ONE { F::ONE } else { F::ZERO }); + let two_res = Term::Unassigned(result, F::from(2)); + let assigned = self + .apply( + ctx, + [two_res, Term::assigned_to_sub(sign)], + -F::ONE, + CombinationOptionCommon::OneLinerAdd.into(), + )? + .swap_remove(0); + + Ok(assigned) + } + /// Enforces one of given two values is `1` /// `(a-1) * (b-1) = 0` fn one_or_one( @@ -266,7 +309,7 @@ pub trait MainGateInstructions: Chip { self.apply( ctx, [Term::assigned_to_sub(a), Term::assigned_to_sub(b)], - F::one(), + F::ONE, CombinationOptionCommon::OneLinerMul.into(), )?; @@ -296,7 +339,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_sub(c2), Term::unassigned_to_add(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(2); @@ -323,7 +366,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_mul(c2), Term::unassigned_to_sub(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(2)) @@ -336,13 +379,13 @@ pub trait MainGateInstructions: Chip { c: &AssignedCondition, ) -> Result, Error> { // Find the new witness - let not_c = c.value().map(|c| F::one() - c); + let not_c = c.value().map(|c| F::ONE - c); Ok(self .apply( ctx, [Term::assigned_to_add(c), Term::unassigned_to_add(not_c)], - -F::one(), + -F::ONE, CombinationOptionCommon::OneLinerAdd.into(), )? .swap_remove(1)) @@ -361,7 +404,7 @@ pub trait MainGateInstructions: Chip { // Non inversion case will never be verified Option::::from(b.invert()) .map(|b_inverted| *a * b_inverted) - .unwrap_or_else(F::zero) + .unwrap_or(F::ZERO) }); Ok(self @@ -372,7 +415,7 @@ pub trait MainGateInstructions: Chip { Term::unassigned_to_mul(c), Term::assigned_to_add(a), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(1)) @@ -401,14 +444,14 @@ pub trait MainGateInstructions: Chip { ) -> Result, Error> { let inverse = a.value().map(|a| { // Non inversion case will never be verified. - a.invert().unwrap_or_else(F::zero) + a.invert().unwrap_or(F::ZERO) }); Ok(self .apply( ctx, [Term::assigned_to_mul(a), Term::unassigned_to_mul(inverse)], - -F::one(), + -F::ONE, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(1)) @@ -421,7 +464,7 @@ pub trait MainGateInstructions: Chip { ctx: &mut RegionCtx<'_, F>, a: &AssignedValue, ) -> Result<(AssignedValue, AssignedCondition), Error> { - let (one, zero) = (F::one(), F::zero()); + let (one, zero) = (F::ONE, F::ZERO); // Returns 'r' as a condition bit that defines if inversion successful or not // First enfoce 'r' to be a bit @@ -511,7 +554,7 @@ pub trait MainGateInstructions: Chip { self.apply( ctx, [Term::assigned_to_add(a), Term::assigned_to_sub(b)], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerAdd.into(), )?; @@ -526,7 +569,7 @@ pub trait MainGateInstructions: Chip { b: &AssignedValue, ) -> Result<(), Error> { // (a - b) must have an inverse - let c = self.sub_with_constant(ctx, a, b, F::zero())?; + let c = self.sub_with_constant(ctx, a, b, F::ZERO)?; self.assert_not_zero(ctx, &c) } @@ -537,7 +580,7 @@ pub trait MainGateInstructions: Chip { a: &AssignedValue, b: &AssignedValue, ) -> Result, Error> { - let (one, zero) = (F::one(), F::zero()); + let (one, zero) = (F::ONE, F::ZERO); // Given a and b equation below is enforced // 0 = (a - b) * (r * (1 - x) + x) + r - 1 @@ -605,7 +648,7 @@ pub trait MainGateInstructions: Chip { /// Enforces that assigned value is zero % w fn assert_zero(&self, ctx: &mut RegionCtx<'_, F>, a: &AssignedValue) -> Result<(), Error> { - self.assert_equal_to_constant(ctx, a, F::zero()) + self.assert_equal_to_constant(ctx, a, F::ZERO) } /// Enforces that assigned value is not zero. @@ -619,13 +662,13 @@ pub trait MainGateInstructions: Chip { let w = a.value().map(|a| { // Non inversion case will never be verified. - a.invert().unwrap_or_else(F::zero) + a.invert().unwrap_or(F::ZERO) }); self.apply( ctx, [Term::assigned_to_mul(a), Term::unassigned_to_mul(w)], - -F::one(), + -F::ONE, CombinationOptionCommon::OneLinerMul.into(), )?; @@ -646,7 +689,7 @@ pub trait MainGateInstructions: Chip { /// Assigns new bit flag `1` if given value eqauls to `1` otherwise assigns /// `0` fn assert_one(&self, ctx: &mut RegionCtx<'_, F>, a: &AssignedValue) -> Result<(), Error> { - self.assert_equal_to_constant(ctx, a, F::one()) + self.assert_equal_to_constant(ctx, a, F::ONE) } /// Assigns a new witness `r` as: @@ -676,7 +719,7 @@ pub trait MainGateInstructions: Chip { a: &AssignedValue, b: &AssignedValue, ) -> Result, Error> { - self.sub_with_constant(ctx, a, b, F::zero()) + self.sub_with_constant(ctx, a, b, F::ZERO) } /// Assigns a new witness `r` as: @@ -740,7 +783,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_add(a), Term::unassigned_to_sub(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerAdd.into(), )? .swap_remove(2)) @@ -763,7 +806,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_add(a), Term::unassigned_to_sub(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerAdd.into(), )? .swap_remove(3)) @@ -787,7 +830,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_mul(b), Term::unassigned_to_sub(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(2)) @@ -817,7 +860,7 @@ pub trait MainGateInstructions: Chip { Term::assigned_to_add(to_add), Term::unassigned_to_sub(c), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )? .swap_remove(3)) @@ -859,7 +902,7 @@ pub trait MainGateInstructions: Chip { self.apply( ctx, [Term::assigned_to_mul(a), Term::assigned_to_mul(b)], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerMul.into(), )?; Ok(()) @@ -873,7 +916,7 @@ pub trait MainGateInstructions: Chip { a: &AssignedValue, b: &AssignedValue, ) -> Result, Error> { - self.add_with_constant(ctx, a, b, F::zero()) + self.add_with_constant(ctx, a, b, F::ZERO) } /// Assigns a new witness `r` as: @@ -932,7 +975,7 @@ pub trait MainGateInstructions: Chip { cond: &AssignedCondition, ) -> Result, Error>; - /// Assignes new value equals to `1` if first bit of `a` is `1` or assigns + /// Assigns new value equals to `1` if first bit of `a` is `1` or assigns /// `0` if first bit of `a` is `0` fn sign( &self, @@ -954,10 +997,10 @@ pub trait MainGateInstructions: Chip { ctx, [ Term::Unassigned(w.map(|w| w.1), F::from(2)), - Term::Assigned(&sign, F::one()), - Term::Assigned(a, -F::one()), + Term::Assigned(&sign, F::ONE), + Term::Assigned(a, -F::ONE), ], - F::zero(), + F::ZERO, CombinationOptionCommon::OneLinerAdd.into(), )?; @@ -994,7 +1037,7 @@ pub trait MainGateInstructions: Chip { .zip(bases.into_iter()) .map(|(bit, base)| Term::Assigned(bit, base)) .collect::>(); - let result = self.compose(ctx, &terms, F::zero())?; + let result = self.compose(ctx, &terms, F::ZERO)?; self.assert_equal(ctx, &result, composed)?; Ok(bits) } @@ -1027,8 +1070,8 @@ pub trait MainGateInstructions: Chip { let mut assigned: Vec> = vec![]; for (i, chunk) in terms.chunks(chunk_width).enumerate() { - let intermediate = Term::Unassigned(remaining, -F::one()); - let constant = if i == 0 { constant } else { F::zero() }; + let intermediate = Term::Unassigned(remaining, -F::ONE); + let constant = if i == 0 { constant } else { F::ZERO }; let mut chunk = chunk.to_vec(); let composed = Term::compose(&chunk[..], constant); @@ -1050,7 +1093,7 @@ pub trait MainGateInstructions: Chip { CombinationOptionCommon::OneLinerAdd // Intermediate round should accumulate the sum } else { - CombinationOptionCommon::CombineToNextAdd(F::one()) + CombinationOptionCommon::CombineToNextAdd(F::ONE) }; enable_lookup(ctx, is_final)?; @@ -1122,7 +1165,7 @@ pub trait MainGateInstructions: Chip { if one_liner { CombinationOptionCommon::OneLinerAdd } else { - CombinationOptionCommon::CombineToNextAdd(-F::one()) + CombinationOptionCommon::CombineToNextAdd(-F::ONE) } .into(), )?; @@ -1141,24 +1184,24 @@ pub trait MainGateInstructions: Chip { .iter() .cloned() .chain(iter::repeat(Term::Zero).take(WIDTH - chunk.len() - 1)) - .chain(iter::once(Term::Unassigned(intermediate_sum, F::one()))), - F::zero(), + .chain(iter::once(Term::Unassigned(intermediate_sum, F::ONE))), + F::ZERO, if i == number_of_chunks - 1 { CombinationOptionCommon::OneLinerAdd } else { - CombinationOptionCommon::CombineToNextAdd(-F::one()) + CombinationOptionCommon::CombineToNextAdd(-F::ONE) } .into(), )?; intermediate_sum = intermediate_sum - .zip(Term::compose(chunk, F::zero())) + .zip(Term::compose(chunk, F::ZERO)) .map(|(cur, result)| cur + result); // // Sanity check for prover // if i == number_of_chunks - 1 { // if let Some(value) = intermediate_sum { - // assert_eq!(value, F::zero()) + // assert_eq!(value, F::ZERO) // }; // } } @@ -1182,12 +1225,7 @@ pub trait MainGateInstructions: Chip { /// Intentionally introduce not to be satisfied witnesses. Use only for /// debug purposes. fn break_here(&self, ctx: &mut RegionCtx<'_, F>) -> Result<(), Error> { - self.apply( - ctx, - [], - F::one(), - CombinationOptionCommon::OneLinerAdd.into(), - )?; + self.apply(ctx, [], F::ONE, CombinationOptionCommon::OneLinerAdd.into())?; Ok(()) } } diff --git a/maingate/src/main_gate.rs b/maingate/src/main_gate.rs index 2416e910..738e263c 100644 --- a/maingate/src/main_gate.rs +++ b/maingate/src/main_gate.rs @@ -8,13 +8,13 @@ //! public_input + //! q_constant = 0 -use crate::halo2::arithmetic::FieldExt; use crate::halo2::circuit::{Chip, Layouter}; use crate::halo2::plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Instance}; use crate::halo2::poly::Rotation; use crate::instructions::{CombinationOptionCommon, MainGateInstructions, Term}; use crate::{AssignedCondition, AssignedValue}; use halo2wrong::halo2::circuit::Value; +use halo2wrong::halo2::ff::PrimeField; use halo2wrong::RegionCtx; use std::{iter, marker::PhantomData}; @@ -93,12 +93,12 @@ impl MainGateConfig { /// MainGate implements instructions with [`MainGateConfig`] #[derive(Clone, Debug)] -pub struct MainGate { +pub struct MainGate { config: MainGateConfig, _marker: PhantomData, } -impl Chip for MainGate { +impl Chip for MainGate { type Config = MainGateConfig; type Loaded = (); @@ -113,7 +113,7 @@ impl Chip for MainGate { /// Additional combination customisations for this gate with two multiplication #[derive(Clone, Debug)] -pub enum CombinationOption { +pub enum CombinationOption { /// Wrapper for common combination options Common(CombinationOptionCommon), /// Activates both of the multiplication gate @@ -123,13 +123,13 @@ pub enum CombinationOption { CombineToNextDoubleMul(F), } -impl From> for CombinationOption { +impl From> for CombinationOption { fn from(option: CombinationOptionCommon) -> Self { CombinationOption::Common(option) } } -impl MainGateInstructions for MainGate { +impl MainGateInstructions for MainGate { type CombinationOption = CombinationOption; type MainGateColumn = MainGateColumn; @@ -212,10 +212,10 @@ impl MainGateInstructions for MainGate { .zip(b.value()) .zip(cond.value()) .map(|((a, b), cond)| { - if *cond == F::one() { + if *cond == F::ONE { *a } else { - assert_eq!(*cond, F::zero()); + assert_eq!(*cond, F::ZERO); *b } }); @@ -229,8 +229,8 @@ impl MainGateInstructions for MainGate { Term::assigned_to_add(b), Term::unassigned_to_sub(res), ], - F::zero(), - CombinationOption::OneLinerDoubleMul(-F::one()), + F::ZERO, + CombinationOption::OneLinerDoubleMul(-F::ONE), )?; ctx.constrain_equal(assigned[0].cell(), assigned[2].cell())?; Ok(assigned.swap_remove(4)) @@ -258,10 +258,10 @@ impl MainGateInstructions for MainGate { .map(|(a, cond)| { ( *a - b, - if *cond == F::one() { + if *cond == F::ONE { *a } else { - assert_eq!(*cond, F::zero()); + assert_eq!(*cond, F::ZERO); b }, ) @@ -337,8 +337,8 @@ impl MainGateInstructions for MainGate { // q_e_next * e + // q_constant = 0 CombinationOptionCommon::CombineToNextMul(next) => { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::one())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ONE)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; ctx.assign_fixed(|| "se_next", self.config.se_next, next)?; } @@ -348,7 +348,7 @@ impl MainGateInstructions for MainGate { // q_constant = 0 CombinationOptionCommon::CombineToNextScaleMul(next, n) => { ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, n)?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; ctx.assign_fixed(|| "se_next", self.config.se_next, next)?; } @@ -356,8 +356,8 @@ impl MainGateInstructions for MainGate { // q_e_next * e + // q_constant = 0 CombinationOptionCommon::CombineToNextAdd(next) => { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::zero())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ZERO)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; ctx.assign_fixed(|| "se_next", self.config.se_next, next)?; } @@ -365,17 +365,17 @@ impl MainGateInstructions for MainGate { // q_mul_ab * a * b + // q_constant = 0 CombinationOptionCommon::OneLinerMul => { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::one())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; - ctx.assign_fixed(|| "se_next", self.config.se_next, F::zero())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ONE)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; + ctx.assign_fixed(|| "se_next", self.config.se_next, F::ZERO)?; } // q_a * a + q_b * b + q_c * c + q_d * d + q_e * e + // q_constant = 0 CombinationOptionCommon::OneLinerAdd => { - ctx.assign_fixed(|| "se_next", self.config.se_next, F::zero())?; - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::zero())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; + ctx.assign_fixed(|| "se_next", self.config.se_next, F::ZERO)?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ZERO)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; } }, @@ -385,8 +385,8 @@ impl MainGateInstructions for MainGate { // q_e_next * e + // q_constant = 0 CombinationOption::CombineToNextDoubleMul(next) => { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::one())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::one())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ONE)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ONE)?; ctx.assign_fixed(|| "se_next", self.config.se_next, next)?; } @@ -395,9 +395,9 @@ impl MainGateInstructions for MainGate { // q_mul_cd * c * d + // q_constant = 0 CombinationOption::OneLinerDoubleMul(e) => { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::one())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ONE)?; ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, e)?; - ctx.assign_fixed(|| "se_next", self.config.se_next, F::zero())?; + ctx.assign_fixed(|| "se_next", self.config.se_next, F::ZERO)?; } }; @@ -415,21 +415,21 @@ impl MainGateInstructions for MainGate { /// Skip this row without any operation fn no_operation(&self, ctx: &mut RegionCtx<'_, F>) -> Result<(), Error> { - ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::zero())?; - ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::zero())?; - ctx.assign_fixed(|| "sc", self.config.sc, F::zero())?; - ctx.assign_fixed(|| "sa", self.config.sa, F::zero())?; - ctx.assign_fixed(|| "sb", self.config.sb, F::zero())?; - ctx.assign_fixed(|| "sd", self.config.sd, F::zero())?; - ctx.assign_fixed(|| "se", self.config.se, F::zero())?; - ctx.assign_fixed(|| "se_next", self.config.se_next, F::zero())?; - ctx.assign_fixed(|| "s_constant", self.config.s_constant, F::zero())?; + ctx.assign_fixed(|| "s_mul_ab", self.config.s_mul_ab, F::ZERO)?; + ctx.assign_fixed(|| "s_mul_cd", self.config.s_mul_cd, F::ZERO)?; + ctx.assign_fixed(|| "sc", self.config.sc, F::ZERO)?; + ctx.assign_fixed(|| "sa", self.config.sa, F::ZERO)?; + ctx.assign_fixed(|| "sb", self.config.sb, F::ZERO)?; + ctx.assign_fixed(|| "sd", self.config.sd, F::ZERO)?; + ctx.assign_fixed(|| "se", self.config.se, F::ZERO)?; + ctx.assign_fixed(|| "se_next", self.config.se_next, F::ZERO)?; + ctx.assign_fixed(|| "s_constant", self.config.s_constant, F::ZERO)?; ctx.next(); Ok(()) } } -impl MainGate { +impl MainGate { /// Create new main gate with given config pub fn new(config: MainGateConfig) -> Self { MainGate { @@ -526,13 +526,12 @@ mod tests { use super::{MainGate, MainGateConfig, Term}; use crate::curves::pasta::Fp; - use crate::halo2::arithmetic::FieldExt; use crate::halo2::circuit::{Layouter, SimpleFloorPlanner, Value}; use crate::halo2::dev::MockProver; use crate::halo2::plonk::{Circuit, ConstraintSystem, Error}; use crate::main_gate::{CombinationOptionCommon, MainGateInstructions}; use crate::AssignedCondition; - use group::ff::PrimeField; + use halo2wrong::halo2::ff::PrimeField; use halo2wrong::utils::{big_to_fe, decompose}; use halo2wrong::RegionCtx; use rand_core::OsRng; @@ -544,7 +543,7 @@ mod tests { } impl TestCircuitConfig { - fn main_gate(&self) -> MainGate { + fn main_gate(&self) -> MainGate { MainGate:: { config: self.main_gate_config.clone(), _marker: PhantomData, @@ -553,12 +552,12 @@ mod tests { } #[derive(Default)] - struct TestCircuitPublicInputs { + struct TestCircuitPublicInputs { _marker: PhantomData, public_input: F, } - impl Circuit for TestCircuitPublicInputs { + impl Circuit for TestCircuitPublicInputs { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -611,11 +610,11 @@ mod tests { } #[derive(Default)] - struct TestCircuitCombination { + struct TestCircuitCombination { _marker: PhantomData, } - impl Circuit for TestCircuitCombination { + impl Circuit for TestCircuitCombination { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -886,12 +885,12 @@ mod tests { } #[derive(Default)] - struct TestCircuitBitness { + struct TestCircuitBitness { neg_path: bool, _marker: PhantomData, } - impl Circuit for TestCircuitBitness { + impl Circuit for TestCircuitBitness { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -918,11 +917,11 @@ mod tests { let ctx = &mut RegionCtx::new(region, offset); if self.neg_path { - let minus_one = -F::one(); + let minus_one = -F::ONE; main_gate.assign_bit(ctx, Value::known(minus_one))?; } else { - let one = F::one(); - let zero = F::zero(); + let one = F::ONE; + let zero = F::ZERO; let u = main_gate.assign_bit(ctx, Value::known(one))?; main_gate.assert_bit(ctx, &u)?; @@ -966,12 +965,12 @@ mod tests { } #[derive(Default)] - struct TestCircuitEquality { + struct TestCircuitEquality { neg_path: bool, _marker: PhantomData, } - impl Circuit for TestCircuitEquality { + impl Circuit for TestCircuitEquality { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1001,8 +1000,8 @@ mod tests { if self.neg_path { } else { - let one = F::one(); - let zero = F::zero(); + let one = F::ONE; + let zero = F::ZERO; let assigned_one = &main_gate.assign_bit(ctx, Value::known(one))?; let assigned_zero = &main_gate.assign_bit(ctx, Value::known(zero))?; @@ -1085,11 +1084,11 @@ mod tests { } #[derive(Default)] - struct TestCircuitArith { + struct TestCircuitArith { _marker: PhantomData, } - impl Circuit for TestCircuitArith { + impl Circuit for TestCircuitArith { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1233,11 +1232,11 @@ mod tests { } #[derive(Default)] - struct TestCircuitConditionals { + struct TestCircuitConditionals { _marker: PhantomData, } - impl Circuit for TestCircuitConditionals { + impl Circuit for TestCircuitConditionals { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1270,7 +1269,7 @@ mod tests { let a = rand(); let b = rand(); - let cond = F::zero(); + let cond = F::ZERO; let a = Value::known(a); let b = Value::known(b); @@ -1284,7 +1283,7 @@ mod tests { let a = rand(); let b = rand(); - let cond = F::one(); + let cond = F::ONE; let a = Value::known(a); let b = Value::known(b); @@ -1298,7 +1297,7 @@ mod tests { let a = rand(); let b_constant = rand(); - let cond = F::zero(); + let cond = F::ZERO; let a = Value::known(a); let b_unassigned = Value::known(b_constant); @@ -1312,7 +1311,7 @@ mod tests { let a = rand(); let b_constant = rand(); - let cond = F::one(); + let cond = F::ONE; let a = Value::known(a); let cond = Value::known(cond); @@ -1347,12 +1346,12 @@ mod tests { } #[derive(Default)] - struct TestCircuitDecomposition { + struct TestCircuitDecomposition { _marker: PhantomData, number_of_bits: usize, } - impl Circuit for TestCircuitDecomposition { + impl Circuit for TestCircuitDecomposition { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1391,7 +1390,7 @@ mod tests { assert_eq!(decomposed.len(), a_decomposed.len()); for (assigned, value) in a_decomposed.iter().zip(decomposed.into_iter()) { - if value == F::zero() { + if value == F::ZERO { main_gate.assert_zero(ctx, assigned)?; } else { main_gate.assert_one(ctx, assigned)?; @@ -1440,11 +1439,11 @@ mod tests { } #[derive(Default)] - struct TestCircuitComposition { + struct TestCircuitComposition { _marker: PhantomData, } - impl Circuit for TestCircuitComposition { + impl Circuit for TestCircuitComposition { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -1509,11 +1508,11 @@ mod tests { } #[derive(Default)] - struct TestCircuitSign { + struct TestCircuitSign { _marker: PhantomData, } - impl Circuit for TestCircuitSign { + impl Circuit for TestCircuitSign { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; diff --git a/maingate/src/range.rs b/maingate/src/range.rs index 13e16a6e..9a4d7c32 100644 --- a/maingate/src/range.rs +++ b/maingate/src/range.rs @@ -1,5 +1,4 @@ use super::main_gate::{MainGate, MainGateConfig}; -use crate::halo2::arithmetic::FieldExt; use crate::halo2::circuit::Chip; use crate::halo2::circuit::Layouter; use crate::halo2::circuit::Value; @@ -8,6 +7,7 @@ use crate::halo2::plonk::{Selector, TableColumn}; use crate::halo2::poly::Rotation; use crate::instructions::{MainGateInstructions, Term}; use crate::AssignedValue; +use halo2wrong::halo2::ff::PrimeField; use halo2wrong::halo2::plonk::Advice; use halo2wrong::halo2::plonk::Column; use halo2wrong::halo2::plonk::Fixed; @@ -35,19 +35,19 @@ pub struct RangeConfig { /// ['RangeChip'] applies binary range constraints #[derive(Clone, Debug)] -pub struct RangeChip { +pub struct RangeChip { config: RangeConfig, main_gate: MainGate, bases: BTreeMap>, } -impl RangeChip { +impl RangeChip { fn main_gate(&self) -> &MainGate { &self.main_gate } } -impl Chip for RangeChip { +impl Chip for RangeChip { type Config = RangeConfig; type Loaded = (); fn config(&self) -> &Self::Config { @@ -59,7 +59,7 @@ impl Chip for RangeChip { } /// Generic chip interface for bitwise ranging values -pub trait RangeInstructions: Chip { +pub trait RangeInstructions: Chip { /// Assigns new witness fn assign( &self, @@ -82,7 +82,7 @@ pub trait RangeInstructions: Chip { fn load_table(&self, layouter: &mut impl Layouter) -> Result<(), Error>; } -impl RangeInstructions for RangeChip { +impl RangeInstructions for RangeChip { fn assign( &self, ctx: &mut RegionCtx<'_, F>, @@ -115,7 +115,7 @@ impl RangeInstructions for RangeChip { .collect(); self.main_gate() - .decompose(ctx, &terms[..], F::zero(), |ctx, is_last| { + .decompose(ctx, &terms[..], F::ZERO, |ctx, is_last| { let composition_tag = self.config .bit_len_tag @@ -164,13 +164,13 @@ impl RangeInstructions for RangeChip { || "table tag", self.config.t_tag, offset, - || Value::known(F::zero()), + || Value::known(F::ZERO), )?; table.assign_cell( || "table value", self.config.t_value, offset, - || Value::known(F::zero()), + || Value::known(F::ZERO), )?; offset += 1; @@ -202,7 +202,7 @@ impl RangeInstructions for RangeChip { } } -impl RangeChip { +impl RangeChip { /// Given config creates new chip that implements ranging pub fn new(config: RangeConfig) -> Self { let main_gate = MainGate::new(config.main_gate_config.clone()); @@ -385,11 +385,11 @@ impl RangeChip { mod tests { use halo2wrong::halo2::circuit::Value; + use halo2wrong::halo2::ff::PrimeField; use halo2wrong::RegionCtx; use super::{RangeChip, RangeConfig, RangeInstructions}; use crate::curves::pasta::Fp; - use crate::halo2::arithmetic::FieldExt; use crate::halo2::circuit::{Layouter, SimpleFloorPlanner}; use crate::halo2::dev::MockProver; use crate::halo2::plonk::{Circuit, ConstraintSystem, Error}; @@ -402,7 +402,7 @@ mod tests { } impl TestCircuitConfig { - fn new( + fn new( meta: &mut ConstraintSystem, composition_bit_lens: Vec, overflow_bit_lens: Vec, @@ -418,28 +418,28 @@ mod tests { Self { range_config } } - fn main_gate(&self) -> MainGate { + fn main_gate(&self) -> MainGate { MainGate::::new(self.range_config.main_gate_config.clone()) } - fn range_chip(&self) -> RangeChip { + fn range_chip(&self) -> RangeChip { RangeChip::::new(self.range_config.clone()) } } #[derive(Clone, Debug)] - struct Input { + struct Input { bit_len: usize, limb_bit_len: usize, value: Value, } #[derive(Default, Clone, Debug)] - struct TestCircuit { + struct TestCircuit { inputs: Vec>, } - impl TestCircuit { + impl TestCircuit { fn composition_bit_lens() -> Vec { vec![8] } @@ -449,7 +449,7 @@ mod tests { } } - impl Circuit for TestCircuit { + impl Circuit for TestCircuit { type Config = TestCircuitConfig; type FloorPlanner = SimpleFloorPlanner; @@ -495,7 +495,7 @@ mod tests { .zip(range_chip.bases(limb_bit_len)) .map(|(limb, base)| Term::Assigned(limb, *base)) .collect(); - let a_1 = main_gate.compose(ctx, &terms[..], F::zero())?; + let a_1 = main_gate.compose(ctx, &terms[..], F::ZERO)?; main_gate.assert_equal(ctx, &a_0, &a_1)?; } diff --git a/transcript/Cargo.toml b/transcript/Cargo.toml index 34a13c88..ed209740 100644 --- a/transcript/Cargo.toml +++ b/transcript/Cargo.toml @@ -6,11 +6,10 @@ edition = "2021" [dependencies] ecc = { path = "../ecc", default-features = false } -poseidon = { git = "https://github.com/privacy-scaling-explorations/poseidon.git", tag = "v2022_10_22" } -group = "0.12" +poseidon = { git = "https://github.com/privacy-scaling-explorations/poseidon.git", branch="main"} subtle = { version = "2.3", default-features = false } [dev-dependencies] rand = "0.8" rand_core = { version = "0.6", default-features = false } -paste = "1.0.7" \ No newline at end of file +paste = "1.0.7" diff --git a/transcript/src/hasher.rs b/transcript/src/hasher.rs index 1c002081..88bafaf2 100644 --- a/transcript/src/hasher.rs +++ b/transcript/src/hasher.rs @@ -1,18 +1,18 @@ use crate::{ - halo2::{arithmetic::FieldExt, plonk::Error}, + halo2::{ff::PrimeField, plonk::Error}, maingate::{AssignedValue, MainGate, MainGateConfig, MainGateInstructions, RegionCtx, Term}, }; use poseidon::{SparseMDSMatrix, Spec, State}; /// `AssignedState` is composed of `T` sized assigned values #[derive(Debug, Clone)] -pub struct AssignedState(pub(super) [AssignedValue; T]); +pub struct AssignedState(pub(super) [AssignedValue; T]); /// `HasherChip` is basically responsible for contraining permutation part of /// transcript pipeline #[derive(Debug, Clone)] pub struct HasherChip< - F: FieldExt, + F: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, const T: usize, @@ -25,7 +25,7 @@ pub struct HasherChip< } impl< - F: FieldExt, + F: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, const T: usize, @@ -63,7 +63,7 @@ impl< } impl< - F: FieldExt, + F: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, const T: usize, @@ -109,7 +109,7 @@ impl< } impl< - F: FieldExt, + F: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, const T: usize, @@ -185,7 +185,7 @@ impl< word, if i == 0 { // Mark - *constant + F::one() + *constant + F::ONE } else { *constant }, @@ -210,7 +210,7 @@ impl< .map(|(e, word)| Term::Assigned(e, *word)) .collect::>>(); - self.main_gate().compose(ctx, &terms[..], F::zero()) + self.main_gate().compose(ctx, &terms[..], F::ZERO) }) .collect::>, Error>>()?; @@ -236,7 +236,7 @@ impl< .zip(mds.row().iter()) .map(|(e, word)| Term::Assigned(e, *word)) .collect::>>(); - let mut new_state = vec![self.main_gate().compose(ctx, &terms[..], F::zero())?]; + let mut new_state = vec![self.main_gate().compose(ctx, &terms[..], F::ZERO)?]; // Rest of the trainsition ie the sparse part for (e, word) in mds.col_hat().iter().zip(self.state.0.iter().skip(1)) { @@ -244,9 +244,9 @@ impl< ctx, &[ Term::Assigned(&self.state.0[0], *e), - Term::Assigned(word, F::one()), + Term::Assigned(word, F::ONE), ], - F::zero(), + F::ZERO, )?); } @@ -292,7 +292,7 @@ impl< self.sbox_full(ctx, constants)?; self.apply_mds(ctx, &mds)?; } - self.sbox_full(ctx, &[F::zero(); T])?; + self.sbox_full(ctx, &[F::ZERO; T])?; self.apply_mds(ctx, &mds)?; Ok(()) diff --git a/transcript/src/transcript.rs b/transcript/src/transcript.rs index 90b61bad..1fe09f0c 100644 --- a/transcript/src/transcript.rs +++ b/transcript/src/transcript.rs @@ -1,23 +1,19 @@ use crate::{ - halo2::{ - arithmetic::{CurveAffine, FieldExt}, - plonk::Error, - }, + halo2::{arithmetic::CurveAffine, plonk::Error}, hasher::HasherChip, maingate::{AssignedValue, RegionCtx}, }; use ecc::{ - halo2::circuit::Chip, + halo2::{circuit::Chip, ff::PrimeField}, maingate::{big_to_fe, decompose, fe_to_big}, AssignedPoint, BaseFieldEccChip, }; -use group::ff::PrimeField; use poseidon::Spec; /// `PointRepresentation` will encode point with an implemented strategy pub trait PointRepresentation< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, >: Default @@ -38,7 +34,7 @@ pub struct LimbRepresentation; impl< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > PointRepresentation for LimbRepresentation @@ -74,7 +70,7 @@ pub struct NativeRepresentation; impl< C: CurveAffine, - N: FieldExt, + N: PrimeField, const NUMBER_OF_LIMBS: usize, const BIT_LEN_LIMB: usize, > PointRepresentation for NativeRepresentation @@ -103,7 +99,7 @@ impl< #[derive(Clone, Debug)] pub struct TranscriptChip< C: CurveAffine, - N: FieldExt, + N: PrimeField, E: PointRepresentation, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, @@ -117,7 +113,7 @@ pub struct TranscriptChip< impl< C: CurveAffine, - N: FieldExt, + N: PrimeField, E: PointRepresentation, const NUMBER_OF_LIMBS: usize, const BIT_LEN: usize, @@ -166,9 +162,9 @@ impl< #[cfg(test)] mod tests { - use crate::halo2::arithmetic::FieldExt; use crate::halo2::circuit::Layouter; use crate::halo2::circuit::SimpleFloorPlanner; + use crate::halo2::ff::{Field, PrimeField}; use crate::halo2::plonk::Error; use crate::halo2::plonk::{Circuit, ConstraintSystem}; use crate::maingate::mock_prover_verify; @@ -185,7 +181,6 @@ mod tests { use ecc::maingate::RangeInstructions; use ecc::BaseFieldEccChip; use ecc::EccConfig; - use group::ff::Field; use paste::paste; use poseidon::Poseidon; use poseidon::Spec; @@ -224,7 +219,10 @@ mod tests { } } - fn config_range(&self, layouter: &mut impl Layouter) -> Result<(), Error> { + fn config_range( + &self, + layouter: &mut impl Layouter, + ) -> Result<(), Error> { let range_chip = RangeChip::::new(self.range_config.clone()); range_chip.load_table(layouter)?;