From 09f3613aac63ebecfbd26e518a36eb59fe404f5c Mon Sep 17 00:00:00 2001 From: Tom Shen Date: Thu, 4 Feb 2021 17:12:23 -0800 Subject: [PATCH] Add DensePolynomialVar (#50) * add folder structures similar to `ark-poly` * add evaluate impl for DensePolynomialVar * add tests * fix no-std * use ark_std::rand instead of SeedableRng * add changelog Co-authored-by: Weikeng Chen --- CHANGELOG.md | 5 +- Cargo.toml | 1 + src/lib.rs | 2 + src/poly/mod.rs | 2 + src/poly/polynomial/mod.rs | 2 + src/poly/polynomial/univariate/dense.rs | 78 +++++++++++++++++++++++++ src/poly/polynomial/univariate/mod.rs | 2 + 7 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/poly/mod.rs create mode 100644 src/poly/polynomial/mod.rs create mode 100644 src/poly/polynomial/univariate/dense.rs create mode 100644 src/poly/polynomial/univariate/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9affa16..e2377e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,15 +3,16 @@ ### Breaking changes - #12 Make the output of the `ToBitsGadget` impl for `FpVar` fixed-size - #48 Add `Clone` trait bound to `CondSelectGadget`. -### Features +### Features +- #21 Add `UInt128` +- #50 Add `DensePolynomialVar` ### Improvements - #5 Speedup BLS-12 pairing - #13 Add `ToConstraintFieldGadget` to `ProjectiveVar` - #15, #16 Allow `cs` to be `None` when converting a Montgomery point into a Twisted Edwards point - #20 Add `CondSelectGadget` impl for `UInt`s -- #21 Add `UInt128` - #22 Reduce density of `three_bit_cond_neg_lookup` - #23 Reduce allocations in `UInt`s - #33 Speedup scalar multiplication by a constant diff --git a/Cargo.toml b/Cargo.toml index 3c83bd7..c865d72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ num-traits = {version = "0.2", default-features = false } [dev-dependencies] ark-test-curves = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = ["bls12_381_scalar_field", "mnt4_753_scalar_field"] } +ark-poly = { git = "https://github.com/arkworks-rs/algebra", default-features = false } [features] default = ["std"] diff --git a/src/lib.rs b/src/lib.rs index 1c3ed05..8ff44b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,8 @@ pub mod pairing; pub mod alloc; /// This module describes a trait for checking equality of variables. pub mod eq; +/// This module implements functions for manipulating polynomial variables over finite fields. +pub mod poly; /// This module describes traits for conditionally selecting a variable from a /// list of variables. pub mod select; diff --git a/src/poly/mod.rs b/src/poly/mod.rs new file mode 100644 index 0000000..fde6e3f --- /dev/null +++ b/src/poly/mod.rs @@ -0,0 +1,2 @@ +/// Modules for working with polynomials in coefficient forms. +pub mod polynomial; diff --git a/src/poly/polynomial/mod.rs b/src/poly/polynomial/mod.rs new file mode 100644 index 0000000..f5a0037 --- /dev/null +++ b/src/poly/polynomial/mod.rs @@ -0,0 +1,2 @@ +/// Module defining data structures for univariate polynomials. +pub mod univariate; diff --git a/src/poly/polynomial/univariate/dense.rs b/src/poly/polynomial/univariate/dense.rs new file mode 100644 index 0000000..04e17fd --- /dev/null +++ b/src/poly/polynomial/univariate/dense.rs @@ -0,0 +1,78 @@ +use ark_ff::PrimeField; +use ark_relations::r1cs::SynthesisError; + +use crate::fields::fp::FpVar; +use crate::fields::FieldVar; +use ark_std::vec::Vec; + +/// Stores a polynomial in coefficient form, where coeffcient is represented by a list of `Fpvar`. +pub struct DensePolynomialVar { + /// The coefficient of `x^i` is stored at location `i` in `self.coeffs`. + pub coeffs: Vec>, +} + +impl DensePolynomialVar { + /// Constructs a new polynomial from a list of coefficients. + pub fn from_coefficients_slice(coeffs: &[FpVar]) -> Self { + Self::from_coefficients_vec(coeffs.to_vec()) + } + + /// Constructs a new polynomial from a list of coefficients. + pub fn from_coefficients_vec(coeffs: Vec>) -> Self { + Self { coeffs } + } + + /// Evaluates `self` at the given `point` and just gives you the gadget for the result. + /// Caution for use in holographic lincheck: The output has 2 entries in one matrix + pub fn evaluate(&self, point: &FpVar) -> Result, SynthesisError> { + let mut result: FpVar = FpVar::zero(); + // current power of point + let mut curr_pow_x: FpVar = FpVar::one(); + for i in 0..self.coeffs.len() { + let term = &curr_pow_x * &self.coeffs[i]; + result += &term; + curr_pow_x *= point; + } + + Ok(result) + } +} + +#[cfg(test)] +mod tests { + use crate::alloc::AllocVar; + use crate::fields::fp::FpVar; + use crate::poly::polynomial::univariate::dense::DensePolynomialVar; + use crate::R1CSVar; + use ark_poly::polynomial::univariate::DensePolynomial; + use ark_poly::{Polynomial, UVPolynomial}; + use ark_relations::r1cs::ConstraintSystem; + use ark_std::vec::Vec; + use ark_std::{test_rng, UniformRand}; + use ark_test_curves::bls12_381::Fr; + + #[test] + fn test_evaluate() { + let mut rng = test_rng(); + for _ in 0..100 { + let cs = ConstraintSystem::new_ref(); + let poly: DensePolynomial = DensePolynomial::rand(10, &mut rng); + let poly_var = { + let coeff: Vec<_> = poly + .coeffs + .iter() + .map(|&x| FpVar::new_witness(ns!(cs, "coeff"), || Ok(x)).unwrap()) + .collect(); + DensePolynomialVar::from_coefficients_vec(coeff) + }; + let point = Fr::rand(&mut rng); + let point_var = FpVar::new_witness(ns!(cs, "point"), || Ok(point)).unwrap(); + + let expected = poly.evaluate(&point); + let actual = poly_var.evaluate(&point_var).unwrap(); + + assert_eq!(actual.value().unwrap(), expected); + assert!(cs.is_satisfied().unwrap()); + } + } +} diff --git a/src/poly/polynomial/univariate/mod.rs b/src/poly/polynomial/univariate/mod.rs new file mode 100644 index 0000000..746c1cd --- /dev/null +++ b/src/poly/polynomial/univariate/mod.rs @@ -0,0 +1,2 @@ +/// A dense univariate polynomial represented in coefficient form. +pub mod dense;