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<ConstraintF: Field>: Eq {
|
|
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
|
&self,
|
|
cs: CS,
|
|
other: &Self,
|
|
condition: &Boolean,
|
|
) -> Result<(), SynthesisError>;
|
|
|
|
fn cost() -> usize;
|
|
}
|
|
impl<T: ConditionalEqGadget<ConstraintF>, ConstraintF: Field> ConditionalEqGadget<ConstraintF>
|
|
for [T]
|
|
{
|
|
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
|
&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<ConstraintF: Field>: Eq
|
|
where
|
|
Self: ConditionalEqGadget<ConstraintF>,
|
|
{
|
|
fn enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
|
&self,
|
|
cs: CS,
|
|
other: &Self,
|
|
) -> Result<(), SynthesisError> {
|
|
self.conditional_enforce_equal(cs, other, &Boolean::constant(true))
|
|
}
|
|
|
|
fn cost() -> usize {
|
|
<Self as ConditionalEqGadget<ConstraintF>>::cost()
|
|
}
|
|
}
|
|
|
|
impl<T: EqGadget<ConstraintF>, ConstraintF: Field> EqGadget<ConstraintF> for [T] {}
|
|
|
|
pub trait NEqGadget<ConstraintF: Field>: Eq {
|
|
fn enforce_not_equal<CS: ConstraintSystem<ConstraintF>>(
|
|
&self,
|
|
cs: CS,
|
|
other: &Self,
|
|
) -> Result<(), SynthesisError>;
|
|
|
|
fn cost() -> usize;
|
|
}
|
|
|
|
pub trait OrEqualsGadget<ConstraintF: Field>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
fn enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
|
cs: CS,
|
|
cond: &Boolean,
|
|
var: &Self,
|
|
first: &Self,
|
|
second: &Self,
|
|
) -> Result<(), SynthesisError>;
|
|
|
|
fn cost() -> usize;
|
|
}
|
|
|
|
impl<ConstraintF: Field, T: Sized + ConditionalOrEqualsGadget<ConstraintF>>
|
|
OrEqualsGadget<ConstraintF> for T
|
|
{
|
|
fn enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
|
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 {
|
|
<Self as ConditionalOrEqualsGadget<ConstraintF>>::cost()
|
|
}
|
|
}
|
|
|
|
pub trait ConditionalOrEqualsGadget<ConstraintF: Field>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
fn conditional_enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
|
cs: CS,
|
|
cond: &Boolean,
|
|
var: &Self,
|
|
first: &Self,
|
|
second: &Self,
|
|
should_enforce: &Boolean,
|
|
) -> Result<(), SynthesisError>;
|
|
|
|
fn cost() -> usize;
|
|
}
|
|
|
|
impl<
|
|
ConstraintF: Field,
|
|
T: Sized + ConditionalEqGadget<ConstraintF> + CondSelectGadget<ConstraintF>,
|
|
> ConditionalOrEqualsGadget<ConstraintF> for T
|
|
{
|
|
fn conditional_enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
|
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 {
|
|
<Self as ConditionalEqGadget<ConstraintF>>::cost()
|
|
+ <Self as CondSelectGadget<ConstraintF>>::cost()
|
|
}
|
|
}
|