Browse Source

Make `mul_by_inverse` use one constraint (#42)

Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
master
Dev Ojha 3 years ago
committed by GitHub
parent
commit
f88d7c6ea3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 10 additions and 31 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +0
    -15
      src/fields/fp/mod.rs
  3. +9
    -16
      src/fields/mod.rs

+ 1
- 0
CHANGELOG.md

@ -23,6 +23,7 @@
- #9 Fix bug in short weierstrass projective curve point's to_affine method
- #29 Fix `to_non_unique_bytes` for `BLS12::G1Prepared`
- #34 Fix `mul_by_inverse` for constants
- #42 Fix regression in `mul_by_inverse` constraint count
## v0.1.0

+ 0
- 15
src/fields/fp/mod.rs

@ -716,21 +716,6 @@ impl FieldVar for FpVar {
}
}
/// Returns (self / denominator), but requires fewer constraints than
/// self * denominator.inverse()
/// It is up to the caller to ensure that denominator is non-zero,
/// since in that case the result is unconstrained.
#[tracing::instrument(target = "r1cs")]
fn mul_by_inverse(&self, denominator: &Self) -> Result<Self, SynthesisError> {
use FpVar::*;
match (self, denominator) {
(Constant(s), Constant(d)) => Ok(Constant(*s / *d)),
(Var(s), Constant(d)) => Ok(Var(s.mul_constant(d.inverse().get()?))),
(Constant(s), Var(d)) => Ok(Var(d.inverse()?.mul_constant(*s))),
(Var(s), Var(d)) => Ok(Var(d.inverse()?.mul(s))),
}
}
#[tracing::instrument(target = "r1cs")]
fn frobenius_map(&self, power: usize) -> Result<Self, SynthesisError> {
match self {

+ 9
- 16
src/fields/mod.rs

@ -5,7 +5,7 @@ use core::{
ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
};
use crate::{prelude::*, Assignment};
use crate::prelude::*;
/// This module contains a generic implementation of cubic extension field
/// variables. That is, it implements the R1CS equivalent of
@ -155,23 +155,16 @@ pub trait FieldVar:
/// Computes `result` such that `self * result == Self::one()`.
fn inverse(&self) -> Result<Self, SynthesisError>;
/// Returns `(self / denominator)`. but requires fewer constraints than
/// `self * denominator.inverse()`.
/// It is up to the caller to ensure that denominator is non-zero,
/// Returns `(self / d)`. but requires fewer constraints than `self * d.inverse()`.
/// It is up to the caller to ensure that `d` is non-zero,
/// since in that case the result is unconstrained.
fn mul_by_inverse(&self, denominator: &Self) -> Result<Self, SynthesisError> {
if denominator.is_constant() {
Ok(denominator.inverse()? * self)
fn mul_by_inverse(&self, d: &Self) -> Result<Self, SynthesisError> {
let d_inv = if self.is_constant() || d.is_constant() {
d.inverse()?
} else {
let result = Self::new_witness(self.cs(), || {
let denominator_inv_native = denominator.value()?.inverse().get()?;
let result = self.value()? * &denominator_inv_native;
Ok(result)
})?;
result.mul_equals(&denominator, &self)?;
Ok(result)
}
Self::new_witness(self.cs(), || Ok(d.value()?.inverse().unwrap_or(F::zero())))?
};
Ok(d_inv * self)
}
/// Computes the frobenius map over `self`.

Loading…
Cancel
Save