Skip to content

Commit

Permalink
Fix panic issues during in-circuit polynomial interpolation (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
winderica authored Oct 17, 2024
1 parent 381abcc commit 8be4bfb
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

- [\#145](https://github.com/arkworks-rs/r1cs-std/pull/145)
- Avoid deeply nested `LinearCombinations` in `EvaluationsVar::interpolate_and_evaluate` to fix the stack overflow issue when calling `.value()` on the evaluation result.
- [\#148](https://github.com/arkworks-rs/r1cs-std/pull/148)
- Fix panic issues during in-circuit polynomial interpolation.

## 0.4.0

Expand Down
33 changes: 21 additions & 12 deletions src/poly/evaluations/univariate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ impl<F: PrimeField> EvaluationsVar<F> {
/// ready to interpolate
pub fn generate_interpolation_cache(&mut self) {
if self.domain.offset().is_constant() {
let poly_evaluations_val: Vec<_> =
self.evals.iter().map(|v| v.value().unwrap()).collect();
let poly_evaluations_val: Vec<_> = self
.evals
.iter()
.map(|v| v.value().unwrap_or_default())
.collect();
let domain = &self.domain;
let lagrange_interpolator = if let &FpVar::Constant(x) = domain.offset() {
LagrangeInterpolator::new(x, domain.gen, domain.dim, poly_evaluations_val)
Expand Down Expand Up @@ -100,7 +103,7 @@ impl<F: PrimeField> EvaluationsVar<F> {
.expect("lagrange interpolator has not been initialized. \
Call `self.generate_interpolation_cache` first or set `interpolate` to true in constructor. ");
let lagrange_coeffs =
lagrange_interpolator.compute_lagrange_coefficients(t.value().unwrap());
lagrange_interpolator.compute_lagrange_coefficients(t.value().unwrap_or_default());
let mut lagrange_coeffs_fg = Vec::new();
// Now we convert these lagrange coefficients to gadgets, and then constrain
// them. The i-th lagrange coefficients constraint is:
Expand All @@ -119,13 +122,15 @@ impl<F: PrimeField> EvaluationsVar<F> {
Ok(lagrange_coeffs[i])
})?;
// Enforce the actual constraint (A_element) * (lagrange_coeff) = 1/Z_I(t)
assert_eq!(
(lagrange_interpolator.v_inv_elems[i] * t.value().unwrap()
- lagrange_interpolator.v_inv_elems[i]
* lagrange_interpolator.all_domain_elems[i])
* lagrange_coeffs[i],
vp_t.value().unwrap()
);
if !cs.is_in_setup_mode() {
assert_eq!(
(lagrange_interpolator.v_inv_elems[i] * t.value().unwrap_or_default()
- lagrange_interpolator.v_inv_elems[i]
* lagrange_interpolator.all_domain_elems[i])
* lagrange_coeffs[i],
vp_t.value().unwrap_or_default()
);
}
a_element.mul_equals(&lag_coeff, &vp_t)?;
lagrange_coeffs_fg.push(lag_coeff);
}
Expand Down Expand Up @@ -344,12 +349,16 @@ impl<'a, F: PrimeField> DivAssign<&'a EvaluationsVar<F>> for EvaluationsVar<F> {
);
let cs = self.evals[0].cs();
// the prover can generate result = (1 / other) * self offline
let mut result_val: Vec<_> = other.evals.iter().map(|x| x.value().unwrap()).collect();
let mut result_val: Vec<_> = other
.evals
.iter()
.map(|x| x.value().unwrap_or_default())
.collect();
batch_inversion(&mut result_val);
result_val
.iter_mut()
.zip(&self.evals)
.for_each(|(a, self_var)| *a *= self_var.value().unwrap());
.for_each(|(a, self_var)| *a *= self_var.value().unwrap_or_default());
let result_var: Vec<_> = result_val
.iter()
.map(|x| FpVar::new_witness(ns!(cs, "div result"), || Ok(*x)).unwrap())
Expand Down

0 comments on commit 8be4bfb

Please sign in to comment.