darkfi/zk/gadget/
is_zero.rs1use halo2_proofs::{
20 circuit::{Region, Value},
21 pasta::group::ff::WithSmallOrderMulGroup,
22 plonk::{Advice, Column, ConstraintSystem, Error, Expression, VirtualCells},
23 poly::Rotation,
24};
25
26#[derive(Clone, Debug)]
27pub struct IsZeroConfig<F> {
28 pub value_inv: Column<Advice>,
29 pub is_zero_expr: Expression<F>,
30}
31
32impl<F: WithSmallOrderMulGroup<3> + Ord> IsZeroConfig<F> {
33 pub fn expr(&self) -> Expression<F> {
34 self.is_zero_expr.clone()
35 }
36}
37
38pub struct IsZeroChip<F: WithSmallOrderMulGroup<3> + Ord> {
39 config: IsZeroConfig<F>,
40}
41
42impl<F: WithSmallOrderMulGroup<3> + Ord> IsZeroChip<F> {
43 pub fn construct(config: IsZeroConfig<F>) -> Self {
44 Self { config }
45 }
46
47 pub fn configure(
48 meta: &mut ConstraintSystem<F>,
49 q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression<F>,
50 value: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression<F>,
51 value_inv: Column<Advice>,
52 ) -> IsZeroConfig<F> {
53 let mut is_zero_expr = Expression::Constant(F::ZERO);
54
55 meta.create_gate("is_zero", |meta| {
56 let value = value(meta);
65 let q_enable = q_enable(meta);
66 let value_inv = meta.query_advice(value_inv, Rotation::cur());
67
68 is_zero_expr = Expression::Constant(F::ONE) - value.clone() * value_inv;
69 vec![q_enable * value * is_zero_expr.clone()]
70 });
71
72 IsZeroConfig { value_inv, is_zero_expr }
73 }
74
75 pub fn assign(
76 &self,
77 region: &mut Region<'_, F>,
78 offset: usize,
79 value: Value<F>,
80 ) -> Result<(), Error> {
81 let value_inv = value.map(|value| value.invert().unwrap_or(F::ZERO));
82 region.assign_advice(|| "value inv", self.config.value_inv, offset, || value_inv)?;
83 Ok(())
84 }
85}