use crate::prelude::*; use algebra::Field; use r1cs_core::{ConstraintSystem, SynthesisError}; /// If `condition == 1`, then enforces that `self` and `other` are equal; /// otherwise, it doesn't enforce anything. pub trait ConditionalEqGadget: Eq { fn conditional_enforce_equal>( &self, cs: CS, other: &Self, condition: &Boolean, ) -> Result<(), SynthesisError>; fn cost() -> usize; } impl, ConstraintF: Field> ConditionalEqGadget for [T] { fn conditional_enforce_equal>( &self, mut cs: CS, other: &Self, condition: &Boolean, ) -> Result<(), SynthesisError> { for (i, (a, b)) in self.iter().zip(other.iter()).enumerate() { let mut cs = cs.ns(|| format!("Iteration {}", i)); a.conditional_enforce_equal(&mut cs, b, condition)?; } Ok(()) } fn cost() -> usize { unimplemented!() } } pub trait EqGadget: Eq where Self: ConditionalEqGadget, { fn enforce_equal>( &self, cs: CS, other: &Self, ) -> Result<(), SynthesisError> { self.conditional_enforce_equal(cs, other, &Boolean::constant(true)) } fn cost() -> usize { >::cost() } } impl, ConstraintF: Field> EqGadget for [T] {} pub trait NEqGadget: Eq { fn enforce_not_equal>( &self, cs: CS, other: &Self, ) -> Result<(), SynthesisError>; fn cost() -> usize; } pub trait OrEqualsGadget where Self: Sized, { fn enforce_equal_or>( cs: CS, cond: &Boolean, var: &Self, first: &Self, second: &Self, ) -> Result<(), SynthesisError>; fn cost() -> usize; } impl> OrEqualsGadget for T { fn enforce_equal_or>( cs: CS, cond: &Boolean, var: &Self, first: &Self, second: &Self, ) -> Result<(), SynthesisError> { Self::conditional_enforce_equal_or(cs, cond, var, first, second, &Boolean::Constant(true)) } fn cost() -> usize { >::cost() } } pub trait ConditionalOrEqualsGadget where Self: Sized, { fn conditional_enforce_equal_or>( cs: CS, cond: &Boolean, var: &Self, first: &Self, second: &Self, should_enforce: &Boolean, ) -> Result<(), SynthesisError>; fn cost() -> usize; } impl< ConstraintF: Field, T: Sized + ConditionalEqGadget + CondSelectGadget, > ConditionalOrEqualsGadget for T { fn conditional_enforce_equal_or>( mut cs: CS, cond: &Boolean, var: &Self, first: &Self, second: &Self, should_enforce: &Boolean, ) -> Result<(), SynthesisError> { let match_opt = Self::conditionally_select( &mut cs.ns(|| "conditional_select_in_or"), cond, first, second, )?; var.conditional_enforce_equal(&mut cs.ns(|| "equals_in_or"), &match_opt, should_enforce) } fn cost() -> usize { >::cost() + >::cost() } }