From 86f652fa9f21e4066e44bb132735989d967584c1 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 4 Mar 2018 19:27:33 -0700 Subject: [PATCH] Some minor documentation/changes to domain. --- src/domain.rs | 61 +++++++++++++++++++++++++++++++++++++++++++-------- src/lib.rs | 4 ++-- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/domain.rs b/src/domain.rs index 6257a80..ff626e5 100644 --- a/src/domain.rs +++ b/src/domain.rs @@ -1,7 +1,20 @@ +//! This module contains an `EvaluationDomain` abstraction for +//! performing various kinds of polynomial arithmetic on top of +//! the scalar field. +//! +//! In pairing-based SNARKs like Groth16, we need to calculate +//! a quotient polynomial over a target polynomial with roots +//! at distinct points associated with each constraint of the +//! constraint system. In order to be efficient, we choose these +//! roots to be the powers of a 2^n root of unity in the field. +//! This allows us to perform polynomial operations in O(n) +//! by performing an O(n log n) FFT over such a domain. + use pairing::{ Engine, Field, - PrimeField + PrimeField, + CurveProjective }; use super::{ @@ -10,8 +23,6 @@ use super::{ use super::multicore::Worker; -const LARGEST_POLYNOMIAL_DEGREE: usize = 1 << 28; - pub struct EvaluationDomain> { coeffs: Vec, exp: u32, @@ -36,12 +47,6 @@ impl> EvaluationDomain { pub fn from_coeffs(mut coeffs: Vec) -> Result, SynthesisError> { - // For platform compatibility, we expect not to - // deal with these kinds of large polynomials. - if coeffs.len() > LARGEST_POLYNOMIAL_DEGREE { - return Err(SynthesisError::PolynomialDegreeTooLarge) - } - // Compute the size of our evaluation domain let mut m = 1; let mut exp = 0; @@ -126,6 +131,8 @@ impl> EvaluationDomain { self.distribute_powers(worker, geninv); } + /// This evaluates t(tau) for this domain, which is + /// tau^m - 1 for these radix-2 domains. pub fn z(&self, tau: &E::Fr) -> E::Fr { let mut tmp = tau.pow(&[self.coeffs.len() as u64]); tmp.sub_assign(&E::Fr::one()); @@ -133,6 +140,9 @@ impl> EvaluationDomain { tmp } + /// The target polynomial is the zero polynomial in our + /// evaluation domain, so we must perform division over + /// a coset. pub fn divide_by_z_on_coset(&mut self, worker: &Worker) { let i = self.z(&E::Fr::multiplicative_generator()).inverse().unwrap(); @@ -148,6 +158,7 @@ impl> EvaluationDomain { }); } + /// Perform O(n) multiplication of two polynomials in the domain. pub fn mul_assign(&mut self, worker: &Worker, other: &EvaluationDomain>) { assert_eq!(self.coeffs.len(), other.coeffs.len()); @@ -162,6 +173,7 @@ impl> EvaluationDomain { }); } + /// Perform O(n) subtraction of one polynomial from another in the domain. pub fn sub_assign(&mut self, worker: &Worker, other: &EvaluationDomain) { assert_eq!(self.coeffs.len(), other.coeffs.len()); @@ -184,6 +196,37 @@ pub trait Group: Sized + Copy + Clone + Send + Sync { fn group_sub_assign(&mut self, other: &Self); } +pub struct Point(pub G); + +impl PartialEq for Point { + fn eq(&self, other: &Point) -> bool { + self.0 == other.0 + } +} + +impl Copy for Point { } + +impl Clone for Point { + fn clone(&self) -> Point { + *self + } +} + +impl Group for Point { + fn group_zero() -> Self { + Point(G::zero()) + } + fn group_mul_assign(&mut self, by: &G::Scalar) { + self.0.mul_assign(by.into_repr()); + } + fn group_add_assign(&mut self, other: &Self) { + self.0.add_assign(&other.0); + } + fn group_sub_assign(&mut self, other: &Self) { + self.0.sub_assign(&other.0); + } +} + pub struct Scalar(pub E::Fr); impl PartialEq for Scalar { diff --git a/src/lib.rs b/src/lib.rs index b3ad471..ddef4a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,8 +7,8 @@ extern crate bit_vec; extern crate crossbeam; extern crate byteorder; -pub mod multicore; -pub mod multiexp; +mod multicore; +mod multiexp; pub mod domain; pub mod groth16;