diff --git a/src/zk/gadget/cond_select.rs b/src/zk/gadget/cond_select.rs index 4735b3f70..3d576a874 100644 --- a/src/zk/gadget/cond_select.rs +++ b/src/zk/gadget/cond_select.rs @@ -22,7 +22,7 @@ use core::marker::PhantomData; use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Region, Value}, + circuit::{AssignedCell, Chip, Layouter, Region}, pasta::group::ff::WithSmallOrderMulGroup, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, @@ -109,12 +109,14 @@ impl + Ord> ConditionalSelectChip { let cond = cond.copy_advice(|| "copy cond", &mut region, config.advices[3], 0)?; - let selected = - if cond.value().copied().to_field() == Value::known(F::ONE).to_field() { - a.value().copied() - } else { - b.value().copied() - }; + let selected = cond + .value() + .copied() + .to_field() + .zip(a.value()) + .zip(b.value()) + .map(|((cond, a), b)| if cond == F::ONE.into() { a } else { b }) + .copied(); let cell = region.assign_advice(|| "select result", config.advices[2], 0, || selected)?; @@ -124,181 +126,3 @@ impl + Ord> ConditionalSelectChip { Ok(out) } } - -#[derive(Clone, Debug)] -pub struct IsEqualConfig + Ord> { - s_is_eq: Selector, - advices: [Column; NUM_OF_UTILITY_ADVICE_COLUMNS], - _marker: PhantomData, -} - -pub struct IsEqualChip + Ord> { - config: IsEqualConfig, - _marker: PhantomData, -} - -impl + Ord> Chip for IsEqualChip { - type Config = IsEqualConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - &self.config - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl + Ord> IsEqualChip { - pub fn construct( - config: >::Config, - _loaded: >::Loaded, - ) -> Self { - Self { config, _marker: PhantomData } - } - - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; NUM_OF_UTILITY_ADVICE_COLUMNS], - ) -> >::Config { - let s_is_eq = meta.selector(); - meta.create_gate("is_eq", |meta| { - let lhs = meta.query_advice(advices[0], Rotation::cur()); - let rhs = meta.query_advice(advices[1], Rotation::cur()); - let out = meta.query_advice(advices[2], Rotation::cur()); - let delta_invert = meta.query_advice(advices[3], Rotation::cur()); - let s_is_eq = meta.query_selector(s_is_eq); - let one = Expression::Constant(F::ONE); - - vec![ - // out is 0 or 1 - s_is_eq.clone() * (out.clone() * (one.clone() - out.clone())), - // if a != b then (a - b) * inverse(a - b) == 1 - out - // if a == b then (a - b) * 1 == 1 - out - s_is_eq.clone() * - ((lhs.clone() - rhs.clone()) * delta_invert.clone() + (out - one.clone())), - // constrain delta_invert: (a - b) * inverse(a - b) must be 1 or 0 - s_is_eq * (lhs.clone() - rhs.clone()) * ((lhs - rhs) * delta_invert - one), - ] - }); - - IsEqualConfig { s_is_eq, advices, _marker: PhantomData } - } - - pub fn is_eq_with_output( - &self, - layouter: &mut impl Layouter, - a: AssignedCell, - b: AssignedCell, - ) -> Result, Error> { - let config = self.config(); - - let out = layouter.assign_region( - || "is_eq", - |mut region: Region<'_, F>| { - config.s_is_eq.enable(&mut region, 0)?; - - let a_field = a.value().copied().to_field(); - let b_field = b.value().copied().to_field(); - - a.copy_advice(|| "copy a", &mut region, config.advices[0], 0)?; - b.copy_advice(|| "copy b", &mut region, config.advices[1], 0)?; - - region.assign_advice( - || "delta invert", - config.advices[3], - 0, - || { - if a_field == b_field { - Value::known(F::ONE) - } else { - let delta = a_field - b_field; - delta.invert().evaluate() - } - }, - )?; - - let is_eq = - if a_field == b_field { Value::known(F::ONE) } else { Value::known(F::ZERO) }; - - let cell = region.assign_advice(|| "is_eq", config.advices[2], 0, || is_eq)?; - Ok(cell) - }, - )?; - - Ok(out) - } -} - -#[derive(Clone, Debug)] -pub struct AssertEqualConfig + Ord> { - s_eq: Selector, - advices: [Column; 2], - _marker: PhantomData, -} - -pub struct AssertEqualChip + Ord> { - config: AssertEqualConfig, - _marker: PhantomData, -} - -impl + Ord> Chip for AssertEqualChip { - type Config = AssertEqualConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - &self.config - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl + Ord> AssertEqualChip { - pub fn construct( - config: >::Config, - _loaded: >::Loaded, - ) -> Self { - Self { config, _marker: PhantomData } - } - - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 2], - ) -> >::Config { - let s_eq = meta.selector(); - meta.create_gate("asset_eq", |meta| { - let lhs = meta.query_advice(advices[0], Rotation::cur()); - let rhs = meta.query_advice(advices[1], Rotation::cur()); - let s_eq = meta.query_selector(s_eq); - - vec![s_eq * (lhs - rhs)] - }); - - AssertEqualConfig { s_eq, advices, _marker: PhantomData } - } - - pub fn assert_equal( - &self, - layouter: &mut impl Layouter, - a: AssignedCell, - b: AssignedCell, - ) -> Result<(), Error> { - let config = self.config(); - - layouter.assign_region( - || "asset_eq", - |mut region: Region<'_, F>| { - config.s_eq.enable(&mut region, 0)?; - - a.copy_advice(|| "copy a", &mut region, config.advices[0], 0)?; - b.copy_advice(|| "copy b", &mut region, config.advices[1], 0)?; - Ok(()) - }, - )?; - - Ok(()) - } -}