@@ -84,13 +84,49 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej_t *prej, s
84
84
#endif
85
85
}
86
86
87
+ /** Fill a table 'prej' with a concatenation of precomputed off multiples of the
88
+ * points in a. Prej will contain the values
89
+ * [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
90
+ * needs space for k * n values. zr[0] will contain prej[0].z / a[0].z. The
91
+ * other zr[i] values = prej[i].z / prej[i-1].z. */
92
+ 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 ) {
93
+ int j ;
94
+ for (j = 0 ; j < k ; j ++ ) {
95
+ secp256k1_gej_t aa ;
96
+ secp256k1_fe_t z2 , z3 ;
97
+ if (j != 0 ) {
98
+ /* Make the Z coordinate of each input a known multiple of the
99
+ * last prej output of the previous input point. */
100
+ secp256k1_fe_sqr (& z2 , & prej [n * j - 1 ].z );
101
+ secp256k1_fe_mul (& z3 , & z2 , & prej [n * j - 1 ].z );
102
+ secp256k1_fe_mul (& aa .x , & a [j ].x , & z2 );
103
+ secp256k1_fe_mul (& aa .y , & a [j ].y , & z3 );
104
+ secp256k1_fe_mul (& aa .z , & a [j ].z , & prej [n * j - 1 ].z );
105
+ aa .infinity = 0 ;
106
+ } else {
107
+ aa = a [0 ];
108
+ }
109
+ secp256k1_ecmult_odd_multiples_table (n , & prej [n * j ], & zr [n * j ], & aa );
110
+ if (j != 0 ) {
111
+ /* Correct the first Z ratio output of this point, by multiplying it
112
+ * with the current point's input Z coordinate, chaining them
113
+ * together */
114
+ secp256k1_fe_mul (zr + n * j , zr + n * j , & a [j ].z );
115
+ }
116
+ }
117
+ }
118
+
87
119
/** Fill a table 'pre' with precomputed odd multiples of a.
88
120
*
89
121
* There are two versions of this function:
90
122
* - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its
91
123
* resulting point set to a single constant Z denominator, stores the X and Y
92
124
* coordinates as ge_storage points in pre, and stores the global Z in rz.
93
125
* It only operates on tables sized for WINDOW_A wnaf multiples.
126
+ * - secp256k1_ecmult_multi_odd_multiples_table_globalz_windowa which is
127
+ * identical to secp256k1_ecmult_odd_multiples_table_globalz_windowa, but
128
+ * works on several input points at once, and brings them all to a single
129
+ * global Z.
94
130
* - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its
95
131
* resulting point set to actually affine points, and stores those in pre.
96
132
* It operates on tables of any size, but uses heap-allocated temporaries.
@@ -109,6 +145,16 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge_t
109
145
secp256k1_ge_globalz_set_table_gej (ECMULT_TABLE_SIZE (WINDOW_A ), pre , globalz , prej , zr );
110
146
}
111
147
148
+ 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 ) {
149
+ secp256k1_gej_t prej [MAX_MULTI * ECMULT_TABLE_SIZE (WINDOW_A )];
150
+ secp256k1_fe_t zr [MAX_MULTI * ECMULT_TABLE_SIZE (WINDOW_A )];
151
+
152
+ /* Compute the odd multiples of all inputs in Jacobian form. */
153
+ secp256k1_ecmult_multi_odd_multiples_table (k , ECMULT_TABLE_SIZE (WINDOW_A ), prej , zr , a );
154
+ /* Bring them to the same Z denominator. */
155
+ secp256k1_ge_globalz_set_table_gej (k * ECMULT_TABLE_SIZE (WINDOW_A ), pre , globalz , prej , zr );
156
+ }
157
+
112
158
static void secp256k1_ecmult_odd_multiples_table_storage_var (int n , secp256k1_ge_storage_t * pre , const secp256k1_gej_t * a ) {
113
159
secp256k1_gej_t * prej = checked_malloc (sizeof (secp256k1_gej_t ) * n );
114
160
secp256k1_ge_t * prea = checked_malloc (sizeof (secp256k1_ge_t ) * n );
@@ -389,4 +435,121 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_ge
389
435
}
390
436
}
391
437
438
+ static void secp256k1_ecmult_mult (const secp256k1_ecmult_context_t * ctx , int points , secp256k1_gej_t * r , const secp256k1_gej_t * a , const secp256k1_scalar_t * na , const secp256k1_scalar_t * ng ) {
439
+ secp256k1_ge_t pre_a [MAX_MULTI ][ECMULT_TABLE_SIZE (WINDOW_A )];
440
+ secp256k1_ge_t tmpa ;
441
+ secp256k1_fe_t Z ;
442
+ #ifdef USE_ENDOMORPHISM
443
+ secp256k1_ge_t pre_a_lam [MAX_MULTI ][ECMULT_TABLE_SIZE (WINDOW_A )];
444
+ secp256k1_scalar_t na_1 [MAX_MULTI ], na_lam [MAX_MULTI ];
445
+ /* Splitted G factors. */
446
+ secp256k1_scalar_t ng_1 , ng_128 ;
447
+ int wnaf_na_1 [MAX_MULTI ][130 ];
448
+ int wnaf_na_lam [MAX_MULTI ][130 ];
449
+ int bits_na_1 [MAX_MULTI ];
450
+ int bits_na_lam [MAX_MULTI ];
451
+ int wnaf_ng_1 [129 ];
452
+ int bits_ng_1 ;
453
+ int wnaf_ng_128 [129 ];
454
+ int bits_ng_128 ;
455
+ #else
456
+ int wnaf_na [MAX_MULTI ][256 ];
457
+ int bits_na [MAX_MULTI ];
458
+ int wnaf_ng [257 ];
459
+ int bits_ng ;
460
+ #endif
461
+ int i ;
462
+ int bits = 0 ;
463
+ int k ;
464
+
465
+ VERIFY_CHECK (points >= 1 );
466
+ VERIFY_CHECK (points <= MAX_MULTI );
467
+
468
+ for (k = 0 ; k < points ; k ++ ) {
469
+ #ifdef USE_ENDOMORPHISM
470
+ /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
471
+ secp256k1_scalar_split_lambda_var (& na_1 [k ], & na_lam [k ], & na [k ]);
472
+
473
+ /* build wnaf representation for na_1 and na_lam. */
474
+ bits_na_1 [k ] = secp256k1_ecmult_wnaf (wnaf_na_1 [k ], & na_1 [k ], WINDOW_A );
475
+ bits_na_lam [k ] = secp256k1_ecmult_wnaf (wnaf_na_lam [k ], & na_lam [k ], WINDOW_A );
476
+ VERIFY_CHECK (bits_na_1 [k ] <= 130 );
477
+ VERIFY_CHECK (bits_na_lam [k ] <= 130 );
478
+ if (bits_na_1 [k ] > bits ) bits = bits_na_1 [k ];
479
+ if (bits_na_lam [k ] > bits ) bits = bits_na_lam [k ];
480
+ #else
481
+ /* build wnaf representation for na. */
482
+ bits_na [k ] = secp256k1_ecmult_wnaf (wnaf_na [k ], & na [k ], WINDOW_A );
483
+ if (bits_na [k ] > bits ) bits = bits_na [k ];
484
+ #endif
485
+ }
486
+
487
+ /* calculate odd multiples of all a's */
488
+ secp256k1_ecmult_multi_odd_multiples_table_globalz_windowa (points , & pre_a [0 ][0 ], & Z , a );
489
+
490
+ #ifdef USE_ENDOMORPHISM
491
+ for (k = 0 ; k < points ; k ++ ) {
492
+ for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
493
+ secp256k1_ge_mul_lambda (& pre_a_lam [k ][i ], & pre_a [k ][i ]);
494
+ }
495
+ }
496
+ #endif
497
+
498
+ #ifdef USE_ENDOMORPHISM
499
+ /* 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) */
500
+ secp256k1_scalar_split_128 (& ng_1 , & ng_128 , ng );
501
+
502
+ /* Build wnaf representation for ng_1 and ng_128 */
503
+ bits_ng_1 = secp256k1_ecmult_wnaf (wnaf_ng_1 , & ng_1 , WINDOW_G );
504
+ bits_ng_128 = secp256k1_ecmult_wnaf (wnaf_ng_128 , & ng_128 , WINDOW_G );
505
+ if (bits_ng_1 > bits ) bits = bits_ng_1 ;
506
+ if (bits_ng_128 > bits ) bits = bits_ng_128 ;
507
+ #else
508
+ bits_ng = secp256k1_ecmult_wnaf (wnaf_ng , ng , WINDOW_G );
509
+ if (bits_ng > bits ) bits = bits_ng ;
510
+ #endif
511
+
512
+ secp256k1_gej_set_infinity (r );
513
+
514
+ for (i = bits - 1 ; i >= 0 ; i -- ) {
515
+ int n ;
516
+ secp256k1_gej_double_var (r , r , NULL );
517
+ #ifdef USE_ENDOMORPHISM
518
+ for (k = 0 ; k < points ; k ++ ) {
519
+ if (i < bits_na_1 [k ] && (n = wnaf_na_1 [k ][i ])) {
520
+ ECMULT_TABLE_GET_GE (& tmpa , pre_a [k ], n , WINDOW_A );
521
+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
522
+ }
523
+ if (i < bits_na_lam [k ] && (n = wnaf_na_lam [k ][i ])) {
524
+ ECMULT_TABLE_GET_GE (& tmpa , pre_a_lam [k ], n , WINDOW_A );
525
+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
526
+ }
527
+ }
528
+ if (i < bits_ng_1 && (n = wnaf_ng_1 [i ])) {
529
+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , * ctx -> pre_g , n , WINDOW_G );
530
+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
531
+ }
532
+ if (i < bits_ng_128 && (n = wnaf_ng_128 [i ])) {
533
+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , * ctx -> pre_g_128 , n , WINDOW_G );
534
+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
535
+ }
536
+ #else
537
+ for (k = 0 ; k < points ; k ++ ) {
538
+ if (i < bits_na [k ] && (n = wnaf_na [k ][i ])) {
539
+ ECMULT_TABLE_GET_GE (& tmpa , pre_a [k ], n , WINDOW_A );
540
+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
541
+ }
542
+ }
543
+ if (i < bits_ng && (n = wnaf_ng [i ])) {
544
+ ECMULT_TABLE_GET_GE_STORAGE (& tmpa , * ctx -> pre_g , n , WINDOW_G );
545
+ secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
546
+ }
547
+ #endif
548
+ }
549
+
550
+ if (!r -> infinity ) {
551
+ secp256k1_fe_mul (& r -> z , & r -> z , & Z );
552
+ }
553
+ }
554
+
392
555
#endif
0 commit comments