1
+ //! This module contains an `EvaluationDomain` abstraction for
2
+ //! performing various kinds of polynomial arithmetic on top of
3
+ //! the scalar field.
4
+ //!
5
+ //! In pairing-based SNARKs like Groth16, we need to calculate
6
+ //! a quotient polynomial over a target polynomial with roots
7
+ //! at distinct points associated with each constraint of the
8
+ //! constraint system. In order to be efficient, we choose these
9
+ //! roots to be the powers of a 2^n root of unity in the field.
10
+ //! This allows us to perform polynomial operations in O(n)
11
+ //! by performing an O(n log n) FFT over such a domain.
12
+
1
13
use pairing:: {
2
14
Engine ,
3
15
Field ,
4
- PrimeField
16
+ PrimeField ,
17
+ CurveProjective
5
18
} ;
6
19
7
20
use super :: {
@@ -10,8 +23,6 @@ use super::{
10
23
11
24
use super :: multicore:: Worker ;
12
25
13
- const LARGEST_POLYNOMIAL_DEGREE : usize = 1 << 28 ;
14
-
15
26
pub struct EvaluationDomain < E : Engine , G : Group < E > > {
16
27
coeffs : Vec < G > ,
17
28
exp : u32 ,
@@ -36,12 +47,6 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
36
47
37
48
pub fn from_coeffs ( mut coeffs : Vec < G > ) -> Result < EvaluationDomain < E , G > , SynthesisError >
38
49
{
39
- // For platform compatibility, we expect not to
40
- // deal with these kinds of large polynomials.
41
- if coeffs. len ( ) > LARGEST_POLYNOMIAL_DEGREE {
42
- return Err ( SynthesisError :: PolynomialDegreeTooLarge )
43
- }
44
-
45
50
// Compute the size of our evaluation domain
46
51
let mut m = 1 ;
47
52
let mut exp = 0 ;
@@ -126,13 +131,18 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
126
131
self . distribute_powers ( worker, geninv) ;
127
132
}
128
133
134
+ /// This evaluates t(tau) for this domain, which is
135
+ /// tau^m - 1 for these radix-2 domains.
129
136
pub fn z ( & self , tau : & E :: Fr ) -> E :: Fr {
130
137
let mut tmp = tau. pow ( & [ self . coeffs . len ( ) as u64 ] ) ;
131
138
tmp. sub_assign ( & E :: Fr :: one ( ) ) ;
132
139
133
140
tmp
134
141
}
135
142
143
+ /// The target polynomial is the zero polynomial in our
144
+ /// evaluation domain, so we must perform division over
145
+ /// a coset.
136
146
pub fn divide_by_z_on_coset ( & mut self , worker : & Worker )
137
147
{
138
148
let i = self . z ( & E :: Fr :: multiplicative_generator ( ) ) . inverse ( ) . unwrap ( ) ;
@@ -148,6 +158,7 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
148
158
} ) ;
149
159
}
150
160
161
+ /// Perform O(n) multiplication of two polynomials in the domain.
151
162
pub fn mul_assign ( & mut self , worker : & Worker , other : & EvaluationDomain < E , Scalar < E > > ) {
152
163
assert_eq ! ( self . coeffs. len( ) , other. coeffs. len( ) ) ;
153
164
@@ -162,6 +173,7 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
162
173
} ) ;
163
174
}
164
175
176
+ /// Perform O(n) subtraction of one polynomial from another in the domain.
165
177
pub fn sub_assign ( & mut self , worker : & Worker , other : & EvaluationDomain < E , G > ) {
166
178
assert_eq ! ( self . coeffs. len( ) , other. coeffs. len( ) ) ;
167
179
@@ -184,6 +196,37 @@ pub trait Group<E: Engine>: Sized + Copy + Clone + Send + Sync {
184
196
fn group_sub_assign ( & mut self , other : & Self ) ;
185
197
}
186
198
199
+ pub struct Point < G : CurveProjective > ( pub G ) ;
200
+
201
+ impl < G : CurveProjective > PartialEq for Point < G > {
202
+ fn eq ( & self , other : & Point < G > ) -> bool {
203
+ self . 0 == other. 0
204
+ }
205
+ }
206
+
207
+ impl < G : CurveProjective > Copy for Point < G > { }
208
+
209
+ impl < G : CurveProjective > Clone for Point < G > {
210
+ fn clone ( & self ) -> Point < G > {
211
+ * self
212
+ }
213
+ }
214
+
215
+ impl < G : CurveProjective > Group < G :: Engine > for Point < G > {
216
+ fn group_zero ( ) -> Self {
217
+ Point ( G :: zero ( ) )
218
+ }
219
+ fn group_mul_assign ( & mut self , by : & G :: Scalar ) {
220
+ self . 0 . mul_assign ( by. into_repr ( ) ) ;
221
+ }
222
+ fn group_add_assign ( & mut self , other : & Self ) {
223
+ self . 0 . add_assign ( & other. 0 ) ;
224
+ }
225
+ fn group_sub_assign ( & mut self , other : & Self ) {
226
+ self . 0 . sub_assign ( & other. 0 ) ;
227
+ }
228
+ }
229
+
187
230
pub struct Scalar < E : Engine > ( pub E :: Fr ) ;
188
231
189
232
impl < E : Engine > PartialEq for Scalar < E > {
0 commit comments