@@ -32,8 +32,11 @@ use multilinear_extensions::{
3232 virtual_poly:: build_eq_x_r_vec,
3333 virtual_polys:: VirtualPolynomialsBuilder ,
3434} ;
35- use p3:: field:: FieldAlgebra ;
36- use rayon:: iter:: { IntoParallelIterator , IntoParallelRefIterator , ParallelIterator } ;
35+ use p3:: field:: { Field , FieldAlgebra } ;
36+ use rayon:: iter:: {
37+ IndexedParallelIterator , IntoParallelIterator , IntoParallelRefIterator ,
38+ IntoParallelRefMutIterator , ParallelIterator ,
39+ } ;
3740use std:: { collections:: BTreeMap , sync:: Arc } ;
3841use sumcheck:: {
3942 macros:: { entered_span, exit_span} ,
@@ -80,16 +83,38 @@ impl CpuEccProver {
8083 let out_rt = transcript. sample_and_append_vec ( b"ecc" , n) ;
8184 let num_threads = optimal_sumcheck_threads ( out_rt. len ( ) ) ;
8285
83- let alpha_pows =
84- transcript. sample_and_append_challenge_pows ( SEPTIC_EXTENSION_DEGREE * 3 , b"ecc_alpha" ) ;
86+ // 2: expression got add and double
87+ // 3: each contribute 3 zero constrains
88+ let alpha_pows = transcript
89+ . sample_and_append_challenge_pows ( SEPTIC_EXTENSION_DEGREE * 3 * 2 , b"ecc_alpha" ) ;
90+ let mut alpha_pows_iter = alpha_pows. iter ( ) ;
8591
8692 let mut expr_builder = VirtualPolynomialsBuilder :: new ( num_threads, out_rt. len ( ) ) ;
8793
8894 let sel_add = SelectorType :: QuarkBinaryTreeLessThan ( 0 . into ( ) ) ;
8995 let mut sel_add_mle: MultilinearExtension < ' _ , E > =
9096 sel_add. compute ( & out_rt, num_instances) . unwrap ( ) ;
97+ // we construct sel_double witness here
98+ // verifier can derive it via `sel_double = 1 - sel_add - last_onehot`
99+ let mut sel_double_mle: Vec < E > = build_eq_x_r_vec ( & out_rt) ;
100+ match sel_add_mle. evaluations ( ) {
101+ FieldType :: Ext ( sel_add_mle) => sel_add_mle
102+ . par_iter ( )
103+ . zip_eq ( sel_double_mle. par_iter_mut ( ) )
104+ . for_each ( |( sel_add, sel_double) | {
105+ if * sel_add != E :: ZERO {
106+ * sel_double = E :: ZERO ;
107+ }
108+ } ) ,
109+ _ => unreachable ! ( ) ,
110+ }
111+ * sel_double_mle. last_mut ( ) . unwrap ( ) = E :: ZERO ;
112+ let mut sel_double_mle = sel_double_mle. into_mle ( ) ;
91113 let sel_add_expr = expr_builder. lift ( sel_add_mle. to_either ( ) ) ;
114+ let sel_double_expr = expr_builder. lift ( sel_double_mle. to_either ( ) ) ;
115+
92116 let mut exprs_add = vec ! [ ] ;
117+ let mut exprs_double = vec ! [ ] ;
93118
94119 let filter_bj = |v : & [ MultilinearExtension < ' _ , E > ] , j : usize | {
95120 v. iter ( )
@@ -162,7 +187,7 @@ impl CpuEccProver {
162187 ( s. clone ( ) * ( & x0 - & x1) - ( & y0 - & y1) )
163188 . to_exprs ( )
164189 . into_iter ( )
165- . zip ( alpha_pows . iter ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
190+ . zip_eq ( alpha_pows_iter . by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
166191 . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
167192 ) ;
168193
@@ -171,11 +196,7 @@ impl CpuEccProver {
171196 ( ( & s * & s) - & x0 - & x1 - & x3)
172197 . to_exprs ( )
173198 . into_iter ( )
174- . zip (
175- alpha_pows[ SEPTIC_EXTENSION_DEGREE ..]
176- . iter ( )
177- . take ( SEPTIC_EXTENSION_DEGREE ) ,
178- )
199+ . zip_eq ( alpha_pows_iter. by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
179200 . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
180201 ) ;
181202
@@ -184,25 +205,56 @@ impl CpuEccProver {
184205 ( s. clone ( ) * ( & x0 - & x3) - ( & y0 + & y3) )
185206 . to_exprs ( )
186207 . into_iter ( )
187- . zip (
188- alpha_pows[ SEPTIC_EXTENSION_DEGREE * 2 ..]
189- . iter ( )
190- . take ( SEPTIC_EXTENSION_DEGREE ) ,
191- )
208+ . zip_eq ( alpha_pows_iter. by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
192209 . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
193210 ) ;
194211
195212 let exprs_add = exprs_add. into_iter ( ) . sum :: < Expression < E > > ( ) * sel_add_expr;
196213
197- let ( zerocheck_proof, state) =
198- IOPProverState :: prove ( expr_builder. to_virtual_polys ( & [ exprs_add] , & [ ] ) , transcript) ;
214+ // deal with double
215+ // 0 = s[0,b] * (2*y[b,0]) - (3*x[b,0]^2 + a)
216+ exprs_double. extend (
217+ ( s. clone ( ) * ( & y0. mul_scalar ( Either :: Left ( E :: BaseField :: TWO ) ) )
218+ - ( ( & x0 * & x0. mul_scalar ( Either :: Left ( E :: BaseField :: from_canonical_u32 ( 3 ) ) ) )
219+ . add_scalar ( Either :: Left ( E :: BaseField :: TWO ) ) ) )
220+ . to_exprs ( )
221+ . into_iter ( )
222+ . zip_eq ( alpha_pows_iter. by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
223+ . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
224+ ) ;
225+
226+ // 0 = s[0,b]^2 - 2*x[b,0] - x[1,b]
227+ exprs_double. extend (
228+ ( ( & s * & s) - ( & x0. mul_scalar ( Either :: Left ( E :: BaseField :: TWO ) ) ) - & x3)
229+ . to_exprs ( )
230+ . into_iter ( )
231+ . zip_eq ( alpha_pows_iter. by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
232+ . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
233+ ) ;
234+
235+ // 0 = s * (x[b,0] - x[1,b]) - (y[b,0] + y[1, b])
236+ exprs_double. extend (
237+ ( s. clone ( ) * ( & x0 - & x3) - ( & y0 + & y3) )
238+ . to_exprs ( )
239+ . into_iter ( )
240+ . zip_eq ( alpha_pows_iter. by_ref ( ) . take ( SEPTIC_EXTENSION_DEGREE ) )
241+ . map ( |( e, alpha) | e * Expression :: Constant ( Either :: Right ( * alpha) ) ) ,
242+ ) ;
243+ assert ! ( alpha_pows_iter. next( ) . is_none( ) ) ;
244+
245+ let exprs_double = exprs_double. into_iter ( ) . sum :: < Expression < E > > ( ) * sel_double_expr;
246+
247+ let ( zerocheck_proof, state) = IOPProverState :: prove (
248+ expr_builder. to_virtual_polys ( & [ exprs_add + exprs_double] , & [ ] ) ,
249+ transcript,
250+ ) ;
199251
200252 let rt = state. collect_raw_challenges ( ) ;
201253 let evals = state. get_mle_flatten_final_evaluations ( ) ;
202254
203255 assert_eq ! ( zerocheck_proof. extract_sum( ) , E :: ZERO ) ;
204256 // 7 for x[rt,0], x[rt,1], y[rt,0], y[rt,1], x[1,rt], y[1,rt], s[0,rt]
205- assert_eq ! ( evals. len( ) , 1 + SEPTIC_EXTENSION_DEGREE * 7 ) ;
257+ assert_eq ! ( evals. len( ) , 2 + SEPTIC_EXTENSION_DEGREE * 7 ) ;
206258
207259 #[ cfg( feature = "sanity-check" ) ]
208260 {
@@ -1055,7 +1107,7 @@ mod tests {
10551107 use std:: iter:: repeat;
10561108
10571109 use ff_ext:: BabyBearExt4 ;
1058- use itertools:: { Itertools , assert_equal } ;
1110+ use itertools:: Itertools ;
10591111 use multilinear_extensions:: {
10601112 mle:: { IntoMLE , MultilinearExtension } ,
10611113 util:: transpose,
0 commit comments