arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
`R1CSVar`: `Option::None` -> `ConstraintSystemRef::None` (#281)

Pratyush Mishra pratyushmishra@berkeley.edu
Wed, 16 Sep 2020 23:09:41 -0700
commit

99e489cac778bcd2631803dd2e42d3606bdb9450

parent

13332bcc1d0594501d825306b5defa4a2aa6f99b

M crypto-primitives/src/merkle_tree/constraints.rs → crypto-primitives/src/merkle_tree/constraints.rs

@@ -37,7 +37,7 @@ // Check that the hash of the given leaf matches the leaf hash in the membership

// proof. let leaf_bits = leaf.to_bytes()?; let leaf_hash = CRHGadget::evaluate(parameters, &leaf_bits)?; - let cs = leaf_hash.cs().or(root.cs()).unwrap(); + let cs = leaf_hash.cs().or(root.cs()); // Check if leaf is one of the bottom-most siblings. let leaf_is_left = Boolean::new_witness(r1cs_core::ns!(cs, "leaf_is_left"), || {
M crypto-primitives/src/prf/blake2s/constraints.rs → crypto-primitives/src/prf/blake2s/constraints.rs

@@ -350,7 +350,7 @@

impl<F: PrimeField> R1CSVar<F> for OutputVar<F> { type Value = [u8; 32]; - fn cs(&self) -> Option<ConstraintSystemRef<F>> { + fn cs(&self) -> ConstraintSystemRef<F> { self.0.cs() }
M r1cs-std/src/bits/boolean.rs → r1cs-std/src/bits/boolean.rs

@@ -232,10 +232,10 @@

impl<F: Field> R1CSVar<F> for Boolean<F> { type Value = bool; - fn cs(&self) -> Option<ConstraintSystemRef<F>> { + fn cs(&self) -> ConstraintSystemRef<F> { match self { - Self::Is(a) | Self::Not(a) => Some(a.cs.clone()), - _ => None, + Self::Is(a) | Self::Not(a) => a.cs.clone(), + _ => ConstraintSystemRef::None, } }

@@ -598,11 +598,10 @@ let r = Self::kary_nand(bits)?;

match r { Constant(true) => Ok(()), Constant(false) => Err(SynthesisError::AssignmentMissing), - Is(_) | Not(_) => r.cs().unwrap().enforce_constraint( - r.lc(), - lc!() + Variable::One, - lc!() + Variable::One, - ), + Is(_) | Not(_) => { + r.cs() + .enforce_constraint(r.lc(), lc!() + Variable::One, lc!() + Variable::One) + } } }

@@ -778,7 +777,7 @@ (Not(a), Not(b)) => lc!() + a.variable() - b.variable(),

}; if condition != &Constant(false) { - let cs = self.cs().or(other.cs()).or(condition.cs()).unwrap(); + let cs = self.cs().or(other.cs()).or(condition.cs()); cs.enforce_constraint(lc!() + difference, condition.lc(), lc!())?; } Ok(())

@@ -814,11 +813,7 @@ (Not(a), Not(b)) => lc!() + a.variable() - b.variable(),

}; if should_enforce != &Constant(false) { - let cs = self - .cs() - .or(other.cs()) - .or(should_enforce.cs()) - .ok_or(SynthesisError::UnconstrainedVariable)?; + let cs = self.cs().or(other.cs()).or(should_enforce.cs()); cs.enforce_constraint(difference, should_enforce.lc(), should_enforce.lc())?; } Ok(())

@@ -863,7 +858,7 @@ (&Constant(false), x) => cond.not().and(x),

(&Constant(true), x) => cond.or(x), (x, &Constant(true)) => cond.not().or(x), (a, b) => { - let cs = cond.cs().unwrap(); + let cs = cond.cs(); let result: Boolean<F> = AllocatedBit::new_witness_without_booleanity_check(cs.clone(), || { let cond = cond.value()?;
M r1cs-std/src/bits/uint.rs → r1cs-std/src/bits/uint.rs

@@ -38,7 +38,7 @@

impl<F: Field> R1CSVar<F> for $name<F> { type Value = $native; - fn cs(&self) -> Option<ConstraintSystemRef<F>> { + fn cs(&self) -> ConstraintSystemRef<F> { self.bits.as_slice().cs() }

@@ -254,7 +254,7 @@ // unpacking the result into allocated bits.

return Ok($name::constant(modular_value.unwrap())); } - let cs = operands.cs().unwrap(); + let cs = operands.cs(); // Storage area for the resulting bits let mut result_bits = vec![];
M r1cs-std/src/bits/uint8.rs → r1cs-std/src/bits/uint8.rs

@@ -18,7 +18,7 @@

impl<F: Field> R1CSVar<F> for UInt8<F> { type Value = u8; - fn cs(&self) -> Option<ConstraintSystemRef<F>> { + fn cs(&self) -> ConstraintSystemRef<F> { self.bits.as_slice().cs() }
M r1cs-std/src/eq.rs → r1cs-std/src/eq.rs

@@ -108,16 +108,16 @@ should_enforce: &Boolean<F>,

) -> Result<(), SynthesisError> { assert_eq!(self.len(), other.len()); let some_are_different = self.is_neq(other)?; - if let Some(cs) = some_are_different.cs().or(should_enforce.cs()) { + if [&some_are_different, should_enforce].is_constant() { + assert!(some_are_different.value().unwrap()); + Ok(()) + } else { + let cs = [&some_are_different, should_enforce].cs(); cs.enforce_constraint( some_are_different.lc(), should_enforce.lc(), should_enforce.lc(), ) - } else { - // `some_are_different` and `should_enforce` are both constants - assert!(some_are_different.value().unwrap()); - Ok(()) } } }
M r1cs-std/src/fields/cubic_extension.rs → r1cs-std/src/fields/cubic_extension.rs

@@ -9,7 +9,7 @@ use crate::fields::fp::FpVar;

use crate::{ fields::{FieldOpsBounds, FieldVar}, prelude::*, - Assignment, ToConstraintFieldGadget, Vec, + ToConstraintFieldGadget, Vec, }; /// This struct is the `R1CS` equivalent of the cubic extension field type

@@ -89,7 +89,7 @@ P: CubicExtVarParams<BF>,

{ type Value = CubicExtField<P>; - fn cs(&self) -> Option<ConstraintSystemRef<P::BasePrimeField>> { + fn cs(&self) -> ConstraintSystemRef<P::BasePrimeField> { [&self.c0, &self.c1, &self.c2].cs() }

@@ -272,7 +272,7 @@ } else {

AllocationMode::Witness }; let inverse = Self::new_variable( - self.cs().get()?.clone(), + self.cs(), || { self.value() .map(|f| f.inverse().unwrap_or(CubicExtField::zero()))
M r1cs-std/src/fields/fp/cmp.rs → r1cs-std/src/fields/fp/cmp.rs

@@ -140,10 +140,11 @@

/// Helper function to enforce `self < other`. This function assumes `self` and `other` /// are `<= (p-1)/2` and does not generate constraints to verify that. fn enforce_smaller_than_unchecked(&self, other: &FpVar<F>) -> Result<(), SynthesisError> { - let cs = [self, other].cs().unwrap(); let is_smaller_than = self.is_smaller_than_unchecked(other)?; let lc_one = lc!() + Variable::One; - cs.enforce_constraint(is_smaller_than.lc(), lc_one.clone(), lc_one) + [self, other] + .cs() + .enforce_constraint(is_smaller_than.lc(), lc_one.clone(), lc_one) } }
M r1cs-std/src/fields/fp/mod.rs → r1cs-std/src/fields/fp/mod.rs

@@ -46,10 +46,10 @@

impl<F: PrimeField> R1CSVar<F> for FpVar<F> { type Value = F; - fn cs(&self) -> Option<ConstraintSystemRef<F>> { + fn cs(&self) -> ConstraintSystemRef<F> { match self { - Self::Constant(_) => Some(ConstraintSystemRef::None), - Self::Var(a) => Some(a.cs.clone()), + Self::Constant(_) => ConstraintSystemRef::None, + Self::Var(a) => a.cs.clone(), } }

@@ -67,7 +67,7 @@ if let Boolean::Constant(b) = other {

Self::Constant(F::from(b as u8)) } else { // `other` is a variable - let cs = other.cs().unwrap(); + let cs = other.cs(); let variable = cs.new_lc(other.lc()).unwrap(); Self::Var(AllocatedFp::new( other.value().ok().map(|b| F::from(b as u8)),

@@ -90,12 +90,9 @@

impl<F: PrimeField> AllocatedFp<F> { /// Constructs `Self` from a `Boolean`: if `other` is false, this outputs `zero`, else it outputs `one`. pub fn from(other: Boolean<F>) -> Self { - if let Some(cs) = other.cs() { - let variable = cs.new_lc(other.lc()).unwrap(); - Self::new(other.value().ok().map(|b| F::from(b as u8)), variable, cs) - } else { - unreachable!("Cannot create a constant value") - } + let cs = other.cs(); + let variable = cs.new_lc(other.lc()).unwrap(); + Self::new(other.value().ok().map(|b| F::from(b as u8)), variable, cs) } /// Returns the value assigned to `self` in the underlying constraint system

@@ -511,7 +508,7 @@ match cond {

Boolean::Constant(true) => Ok(true_val.clone()), Boolean::Constant(false) => Ok(false_val.clone()), _ => { - let cs = cond.cs().unwrap(); + let cs = cond.cs(); let result = Self::new_witness(cs.clone(), || { cond.value() .and_then(|c| if c { true_val } else { false_val }.value.get())

@@ -541,24 +538,20 @@ #[tracing::instrument(target = "r1cs")]

fn two_bit_lookup(b: &[Boolean<F>], c: &[Self::TableConstant]) -> Result<Self, SynthesisError> { debug_assert_eq!(b.len(), 2); debug_assert_eq!(c.len(), 4); - if let Some(cs) = b.cs() { - let result = Self::new_witness(cs.clone(), || { - let lsb = usize::from(b[0].value()?); - let msb = usize::from(b[1].value()?); - let index = lsb + (msb << 1); - Ok(c[index]) - })?; - let one = Variable::One; - cs.enforce_constraint( - lc!() + b[1].lc() * (c[3] - &c[2] - &c[1] + &c[0]) + (c[1] - &c[0], one), - lc!() + b[0].lc(), - lc!() + result.variable - (c[0], one) + b[1].lc() * (c[0] - &c[2]), - )?; + let result = Self::new_witness(b.cs(), || { + let lsb = usize::from(b[0].value()?); + let msb = usize::from(b[1].value()?); + let index = lsb + (msb << 1); + Ok(c[index]) + })?; + let one = Variable::One; + b.cs().enforce_constraint( + lc!() + b[1].lc() * (c[3] - &c[2] - &c[1] + &c[0]) + (c[1] - &c[0], one), + lc!() + b[0].lc(), + lc!() + result.variable - (c[0], one) + b[1].lc() * (c[0] - &c[2]), + )?; - Ok(result) - } else { - unreachable!("must provide a way to obtain a ConstraintSystemRef") - } + Ok(result) } }

@@ -573,37 +566,32 @@ c: &[Self::TableConstant],

) -> Result<Self, SynthesisError> { debug_assert_eq!(b.len(), 3); debug_assert_eq!(c.len(), 4); - - if let Some(cs) = b.cs() { - let result = Self::new_witness(cs.clone(), || { - let lsb = usize::from(b[0].value()?); - let msb = usize::from(b[1].value()?); - let index = lsb + (msb << 1); - let intermediate = c[index]; + let result = Self::new_witness(b.cs(), || { + let lsb = usize::from(b[0].value()?); + let msb = usize::from(b[1].value()?); + let index = lsb + (msb << 1); + let intermediate = c[index]; - let is_negative = b[2].value()?; - let y = if is_negative { - -intermediate - } else { - intermediate - }; - Ok(y) - })?; + let is_negative = b[2].value()?; + let y = if is_negative { + -intermediate + } else { + intermediate + }; + Ok(y) + })?; - let y_lc = b0b1.lc() * (c[3] - &c[2] - &c[1] + &c[0]) - + b[0].lc() * (c[1] - &c[0]) - + b[1].lc() * (c[2] - &c[0]) - + (c[0], Variable::One); - cs.enforce_constraint( - y_lc.clone() + y_lc.clone(), - b[2].lc(), - y_lc.clone() - result.variable, - )?; + let y_lc = b0b1.lc() * (c[3] - &c[2] - &c[1] + &c[0]) + + b[0].lc() * (c[1] - &c[0]) + + b[1].lc() * (c[2] - &c[0]) + + (c[0], Variable::One); + b.cs().enforce_constraint( + y_lc.clone() + y_lc.clone(), + b[2].lc(), + y_lc.clone() - result.variable, + )?; - Ok(result) - } else { - unreachable!("must provide a way to obtain a ConstraintSystemRef") - } + Ok(result) } }

@@ -938,7 +926,7 @@ // cond * t + (1 - cond) * f

Ok(is.mul_constant(*t).add(&not.mul_constant(*f)).into()) } (_, _) => { - let cs = cond.cs().unwrap(); + let cs = cond.cs(); let true_value = match true_value { Self::Constant(f) => AllocatedFp::new_constant(cs.clone(), f)?, Self::Var(v) => v.clone(),

@@ -964,13 +952,13 @@ #[tracing::instrument(target = "r1cs")]

fn two_bit_lookup(b: &[Boolean<F>], c: &[Self::TableConstant]) -> Result<Self, SynthesisError> { debug_assert_eq!(b.len(), 2); debug_assert_eq!(c.len(), 4); - if b.cs().is_some() { - AllocatedFp::two_bit_lookup(b, c).map(Self::Var) - } else { + if b.is_constant() { let lsb = usize::from(b[0].value()?); let msb = usize::from(b[1].value()?); let index = lsb + (msb << 1); Ok(Self::Constant(c[index])) + } else { + AllocatedFp::two_bit_lookup(b, c).map(Self::Var) } } }

@@ -987,9 +975,9 @@ ) -> Result<Self, SynthesisError> {

debug_assert_eq!(b.len(), 3); debug_assert_eq!(c.len(), 4); - if b.cs().or(b0b1.cs()).is_some() { - AllocatedFp::three_bit_cond_neg_lookup(b, b0b1, c).map(Self::Var) - } else { + if !b.cs().or(b0b1.cs()).is_none() { + // We only have constants + let lsb = usize::from(b[0].value()?); let msb = usize::from(b[1].value()?); let index = lsb + (msb << 1);

@@ -1002,6 +990,8 @@ } else {

intermediate }; Ok(Self::Constant(y)) + } else { + AllocatedFp::three_bit_cond_neg_lookup(b, b0b1, c).map(Self::Var) } } }
M r1cs-std/src/fields/mod.rs → r1cs-std/src/fields/mod.rs

@@ -152,7 +152,7 @@ /// `self * denominator.inverse()`.

/// It is up to the caller to ensure that denominator is non-zero, /// since in that case the result is unconstrained. fn mul_by_inverse(&self, denominator: &Self) -> Result<Self, SynthesisError> { - let result = Self::new_witness(self.cs().unwrap(), || { + let result = Self::new_witness(self.cs(), || { let denominator_inv_native = denominator.value()?.inverse().get()?; let result = self.value()? * &denominator_inv_native; Ok(result)
M r1cs-std/src/fields/quadratic_extension.rs → r1cs-std/src/fields/quadratic_extension.rs

@@ -9,7 +9,7 @@ use crate::fields::fp::FpVar;

use crate::{ fields::{FieldOpsBounds, FieldVar}, prelude::*, - Assignment, ToConstraintFieldGadget, Vec, + ToConstraintFieldGadget, Vec, }; /// This struct is the `R1CS` equivalent of the quadratic extension field type

@@ -122,7 +122,7 @@ P: QuadExtVarParams<BF>,

{ type Value = QuadExtField<P>; - fn cs(&self) -> Option<ConstraintSystemRef<P::BasePrimeField>> { + fn cs(&self) -> ConstraintSystemRef<P::BasePrimeField> { [&self.c0, &self.c1].cs() }

@@ -279,7 +279,7 @@ } else {

AllocationMode::Witness }; let inverse = Self::new_variable( - self.cs().get()?.clone(), + self.cs(), || { self.value() .map(|f| f.inverse().unwrap_or(QuadExtField::zero()))
M r1cs-std/src/groups/curves/short_weierstrass/mod.rs → r1cs-std/src/groups/curves/short_weierstrass/mod.rs

@@ -119,7 +119,7 @@ for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,

{ type Value = SWProjective<P>; - fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> { + fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> { self.x.cs().or(self.y.cs()).or(self.z.cs()) }

@@ -152,7 +152,7 @@

/// Convert this point into affine form. #[tracing::instrument(target = "r1cs")] pub fn to_affine(&self) -> Result<AffineVar<P, F>, SynthesisError> { - let cs = self.cs().unwrap_or(ConstraintSystemRef::None); + let cs = self.cs(); let mode = if self.is_constant() { let point = self.value()?.into_affine(); let x = F::new_constant(ConstraintSystemRef::None, point.x)?;
M r1cs-std/src/groups/curves/twisted_edwards/mod.rs → r1cs-std/src/groups/curves/twisted_edwards/mod.rs

@@ -49,7 +49,7 @@ for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,

{ type Value = (P::BaseField, P::BaseField); - fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> { + fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> { self.x.cs().or(self.y.cs()) }

@@ -112,7 +112,7 @@

/// Converts `self` into a Twisted Edwards curve point variable. #[tracing::instrument(target = "r1cs")] pub fn into_edwards(&self) -> Result<AffineVar<P, F>, SynthesisError> { - let cs = self.cs().unwrap_or(ConstraintSystemRef::None); + let cs = self.cs(); // Compute u = x / y let u = F::new_witness(r1cs_core::ns!(cs, "u"), || { let y_inv = self

@@ -153,12 +153,11 @@

#[tracing::instrument(target = "r1cs")] fn add(self, other: &'a Self) -> Self::Output { let cs = [&self, other].cs(); - let mode = if cs.is_none() || matches!(cs, Some(ConstraintSystemRef::None)) { + let mode = if cs.is_none() { AllocationMode::Constant } else { AllocationMode::Witness }; - let cs = cs.unwrap_or(ConstraintSystemRef::None); let coeff_b = P::MontgomeryModelParameters::COEFF_B; let coeff_a = P::MontgomeryModelParameters::COEFF_A;

@@ -378,7 +377,7 @@ for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,

{ type Value = TEProjective<P>; - fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> { + fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> { self.x.cs().or(self.y.cs()) }

@@ -465,7 +464,7 @@ if self.is_constant() {

let value = self.value()?; *self = Self::constant(value.double()); } else { - let cs = self.cs().unwrap(); + let cs = self.cs(); let a = P::COEFF_A; // xy

@@ -714,7 +713,7 @@ if [this, other].is_constant() {

assert!(this.is_constant() && other.is_constant()); AffineVar::constant(this.value().unwrap() + &other.value().unwrap()) } else { - let cs = [this, other].cs().unwrap(); + let cs = [this, other].cs(); let a = P::COEFF_A; let d = P::COEFF_D;
M r1cs-std/src/lib.rs → r1cs-std/src/lib.rs

@@ -119,12 +119,13 @@ /// The type of the "native" value that `Self` represents in the constraint system.

type Value: core::fmt::Debug + Eq + Clone; /// Returns the underlying `ConstraintSystemRef`. - fn cs(&self) -> Option<r1cs_core::ConstraintSystemRef<F>>; + /// + /// If `self` is a constant value, then this *must* return `r1cs_core::ConstraintSystemRef::None`. + fn cs(&self) -> r1cs_core::ConstraintSystemRef<F>; /// Returns `true` if `self` is a circuit-generation-time constant. fn is_constant(&self) -> bool { - self.cs() - .map_or(true, |cs| cs == r1cs_core::ConstraintSystemRef::None) + self.cs().is_none() } /// Returns the value that is assigned to `self` in the underlying

@@ -135,8 +136,8 @@

impl<F: Field, T: R1CSVar<F>> R1CSVar<F> for [T] { type Value = Vec<T::Value>; - fn cs(&self) -> Option<r1cs_core::ConstraintSystemRef<F>> { - let mut result = None; + fn cs(&self) -> r1cs_core::ConstraintSystemRef<F> { + let mut result = r1cs_core::ConstraintSystemRef::None; for var in self { result = var.cs().or(result); }

@@ -155,7 +156,7 @@

impl<'a, F: Field, T: 'a + R1CSVar<F>> R1CSVar<F> for &'a T { type Value = T::Value; - fn cs(&self) -> Option<r1cs_core::ConstraintSystemRef<F>> { + fn cs(&self) -> r1cs_core::ConstraintSystemRef<F> { (*self).cs() }