@@ -77,13 +77,49 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej_t *prej, s
7777#endif
7878}
7979
80+ /** Fill a table 'prej' with a concatenation of precomputed off multiples of the
81+ * points in a. Prej will contain the values
82+ * [1*a[0],3*a[0],...,(2*n-1)*a[0],1*a[1],3*a[1],...,(2*n-1)*a[k-1]], so it
83+ * needs space for k * n values. zr[0] will contain prej[0].z / a[0].z. The
84+ * other zr[i] values = prej[i].z / prej[i-1].z. */
85+ static void secp256k1_ecmult_multi_odd_multiples_table (int k , int n , secp256k1_gej_t * prej , secp256k1_fe_t * zr , const secp256k1_gej_t * a ) {
86+ int j ;
87+ for (j = 0 ; j < k ; j ++ ) {
88+ secp256k1_gej_t aa ;
89+ secp256k1_fe_t z2 , z3 ;
90+ if (j != 0 ) {
91+ /* Make the Z coordinate of each input a known multiple of the
92+ * last prej output of the previous input point. */
93+ secp256k1_fe_sqr (& z2 , & prej [n * j - 1 ].z );
94+ secp256k1_fe_mul (& z3 , & z2 , & prej [n * j - 1 ].z );
95+ secp256k1_fe_mul (& aa .x , & a [j ].x , & z2 );
96+ secp256k1_fe_mul (& aa .y , & a [j ].y , & z3 );
97+ secp256k1_fe_mul (& aa .z , & a [j ].z , & prej [n * j - 1 ].z );
98+ aa .infinity = 0 ;
99+ } else {
100+ aa = a [0 ];
101+ }
102+ secp256k1_ecmult_odd_multiples_table (n , & prej [n * j ], & zr [n * j ], & aa );
103+ if (j != 0 ) {
104+ /* Correct the first Z ratio output of this point, by multiplying it
105+ * with the current point's input Z coordinate, chaining them
106+ * together */
107+ secp256k1_fe_mul (zr + n * j , zr + n * j , & a [j ].z );
108+ }
109+ }
110+ }
111+
80112/** Fill a table 'pre' with precomputed odd multiples of a.
81113 *
82114 * There are two versions of this function:
83115 * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
84116 * resulting point set to a single constant Z denominator, stores the X and Y
85117 * coordinates as ge_storage points in pre, and stores the global Z in rz.
86118 * It only operates on tables sized for WINDOW_A wnaf multiples.
119+ * - secp256k1_ecmult_multi_odd_multiples_table_globalz_windowa which is
120+ * identical to secp256k1_ecmult_odd_multiples_table_globalz_windowa, but
121+ * works on several input points at once, and brings them all to a single
122+ * global Z.
87123 * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
88124 * resulting point set to actually affine points, and stores those in pre.
89125 * It operates on tables of any size, but uses heap-allocated temporaries.
@@ -102,6 +138,16 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge_t
102138 secp256k1_ge_globalz_set_table_gej (ECMULT_TABLE_SIZE (WINDOW_A ), pre , globalz , prej , zr );
103139}
104140
141+ static void secp256k1_ecmult_multi_odd_multiples_table_globalz_windowa (int k , secp256k1_ge_t * pre , secp256k1_fe_t * globalz , const secp256k1_gej_t * a ) {
142+ secp256k1_gej_t prej [MAX_MULTI * ECMULT_TABLE_SIZE (WINDOW_A )];
143+ secp256k1_fe_t zr [MAX_MULTI * ECMULT_TABLE_SIZE (WINDOW_A )];
144+
145+ /* Compute the odd multiples of all inputs in Jacobian form. */
146+ secp256k1_ecmult_multi_odd_multiples_table (k , ECMULT_TABLE_SIZE (WINDOW_A ), prej , zr , a );
147+ /* Bring them to the same Z denominator. */
148+ secp256k1_ge_globalz_set_table_gej (k * ECMULT_TABLE_SIZE (WINDOW_A ), pre , globalz , prej , zr );
149+ }
150+
105151static void secp256k1_ecmult_odd_multiples_table_storage_var (int n , secp256k1_ge_storage_t * pre , const secp256k1_gej_t * a ) {
106152 secp256k1_gej_t * prej = checked_malloc (sizeof (secp256k1_gej_t ) * n );
107153 secp256k1_ge_t * prea = checked_malloc (sizeof (secp256k1_ge_t ) * n );
@@ -353,4 +399,122 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
353399 }
354400}
355401
402+ static void secp256k1_ecmult_mult (int points , secp256k1_gej_t * r , const secp256k1_gej_t * a , const secp256k1_scalar_t * na , const secp256k1_scalar_t * ng ) {
403+ secp256k1_ge_t pre_a [MAX_MULTI ][ECMULT_TABLE_SIZE (WINDOW_A )];
404+ secp256k1_ge_t tmpa ;
405+ secp256k1_fe_t Z ;
406+ const secp256k1_ecmult_consts_t * c = secp256k1_ecmult_consts ;
407+ #ifdef USE_ENDOMORPHISM
408+ secp256k1_ge_t pre_a_lam [MAX_MULTI ][ECMULT_TABLE_SIZE (WINDOW_A )];
409+ secp256k1_scalar_t na_1 [MAX_MULTI ], na_lam [MAX_MULTI ];
410+ /* Splitted G factors. */
411+ secp256k1_scalar_t ng_1 , ng_128 ;
412+ int wnaf_na_1 [MAX_MULTI ][130 ];
413+ int wnaf_na_lam [MAX_MULTI ][130 ];
414+ int bits_na_1 [MAX_MULTI ];
415+ int bits_na_lam [MAX_MULTI ];
416+ int wnaf_ng_1 [129 ];
417+ int bits_ng_1 ;
418+ int wnaf_ng_128 [129 ];
419+ int bits_ng_128 ;
420+ #else
421+ int wnaf_na [MAX_MULTI ][256 ];
422+ int bits_na [MAX_MULTI ];
423+ int wnaf_ng [257 ];
424+ int bits_ng ;
425+ #endif
426+ int i ;
427+ int bits = 0 ;
428+ int k ;
429+
430+ VERIFY_CHECK (points >= 1 );
431+ VERIFY_CHECK (points <= MAX_MULTI );
432+
433+ for (k = 0 ; k < points ; k ++ ) {
434+ #ifdef USE_ENDOMORPHISM
435+ /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
436+ secp256k1_scalar_split_lambda_var (& na_1 [k ], & na_lam [k ], & na [k ]);
437+
438+ /* build wnaf representation for na_1 and na_lam. */
439+ bits_na_1 [k ] = secp256k1_ecmult_wnaf (wnaf_na_1 [k ], & na_1 [k ], WINDOW_A );
440+ bits_na_lam [k ] = secp256k1_ecmult_wnaf (wnaf_na_lam [k ], & na_lam [k ], WINDOW_A );
441+ VERIFY_CHECK (bits_na_1 [k ] <= 130 );
442+ VERIFY_CHECK (bits_na_lam [k ] <= 130 );
443+ if (bits_na_1 [k ] > bits ) bits = bits_na_1 [k ];
444+ if (bits_na_lam [k ] > bits ) bits = bits_na_lam [k ];
445+ #else
446+ /* build wnaf representation for na. */
447+ bits_na [k ] = secp256k1_ecmult_wnaf (wnaf_na [k ], & na [k ], WINDOW_A );
448+ if (bits_na [k ] > bits ) bits = bits_na [k ];
449+ #endif
450+ }
451+
452+ /* calculate odd multiples of all a's */
453+ secp256k1_ecmult_multi_odd_multiples_table_globalz_windowa (points , & pre_a [0 ][0 ], & Z , a );
454+
455+ #ifdef USE_ENDOMORPHISM
456+ for (k = 0 ; k < points ; k ++ ) {
457+ for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
458+ secp256k1_ge_mul_lambda (& pre_a_lam [k ][i ], & pre_a [k ][i ]);
459+ }
460+ }
461+ #endif
462+
463+ #ifdef USE_ENDOMORPHISM
464+ /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
465+ secp256k1_scalar_split_128 (& ng_1 , & ng_128 , ng );
466+
467+ /* Build wnaf representation for ng_1 and ng_128 */
468+ bits_ng_1 = secp256k1_ecmult_wnaf (wnaf_ng_1 , & ng_1 , WINDOW_G );
469+ bits_ng_128 = secp256k1_ecmult_wnaf (wnaf_ng_128 , & ng_128 , WINDOW_G );
470+ if (bits_ng_1 > bits ) bits = bits_ng_1 ;
471+ if (bits_ng_128 > bits ) bits = bits_ng_128 ;
472+ #else
473+ bits_ng = secp256k1_ecmult_wnaf (wnaf_ng , ng , WINDOW_G );
474+ if (bits_ng > bits ) bits = bits_ng ;
475+ #endif
476+
477+ secp256k1_gej_set_infinity (r );
478+
479+ for (i = bits - 1 ; i >= 0 ; i -- ) {
480+ int n ;
481+ secp256k1_gej_double_var (r , r , NULL );
482+ #ifdef USE_ENDOMORPHISM
483+ for (k = 0 ; k < points ; k ++ ) {
484+ if (i < bits_na_1 [k ] && (n = wnaf_na_1 [k ][i ])) {
485+ ECMULT_TABLE_GET_GE (& tmpa , pre_a [k ], n , WINDOW_A );
486+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
487+ }
488+ if (i < bits_na_lam [k ] && (n = wnaf_na_lam [k ][i ])) {
489+ ECMULT_TABLE_GET_GE (& tmpa , pre_a_lam [k ], n , WINDOW_A );
490+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
491+ }
492+ }
493+ if (i < bits_ng_1 && (n = wnaf_ng_1 [i ])) {
494+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , c -> pre_g , n , WINDOW_G );
495+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
496+ }
497+ if (i < bits_ng_128 && (n = wnaf_ng_128 [i ])) {
498+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , c -> pre_g_128 , n , WINDOW_G );
499+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
500+ }
501+ #else
502+ for (k = 0 ; k < points ; k ++ ) {
503+ if (i < bits_na [k ] && (n = wnaf_na [k ][i ])) {
504+ ECMULT_TABLE_GET_GE (& tmpa , pre_a [k ], n , WINDOW_A );
505+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
506+ }
507+ }
508+ if (i < bits_ng && (n = wnaf_ng [i ])) {
509+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , c -> pre_g , n , WINDOW_G );
510+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
511+ }
512+ #endif
513+ }
514+
515+ if (!r -> infinity ) {
516+ secp256k1_fe_mul (& r -> z , & r -> z , & Z );
517+ }
518+ }
519+
356520#endif
0 commit comments