11/**********************************************************************
2- * Copyright (c) 2013, 2014 Pieter Wuille *
2+ * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra *
33 * Distributed under the MIT software license, see the accompanying *
44 * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
55 **********************************************************************/
@@ -283,50 +283,78 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
283283 return last_set_bit + 1 ;
284284}
285285
286- static void secp256k1_ecmult (const secp256k1_ecmult_context * ctx , secp256k1_gej * r , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
287- secp256k1_ge pre_a [ECMULT_TABLE_SIZE (WINDOW_A )];
288- secp256k1_ge tmpa ;
289- secp256k1_fe Z ;
286+ struct secp256k1_strauss_point_state {
290287#ifdef USE_ENDOMORPHISM
291- secp256k1_ge pre_a_lam [ECMULT_TABLE_SIZE (WINDOW_A )];
292288 secp256k1_scalar na_1 , na_lam ;
293- /* Splitted G factors. */
294- secp256k1_scalar ng_1 , ng_128 ;
295289 int wnaf_na_1 [130 ];
296290 int wnaf_na_lam [130 ];
297291 int bits_na_1 ;
298292 int bits_na_lam ;
299- int wnaf_ng_1 [129 ];
300- int bits_ng_1 ;
301- int wnaf_ng_128 [129 ];
302- int bits_ng_128 ;
303293#else
304294 int wnaf_na [256 ];
305295 int bits_na ;
296+ #endif
297+ size_t input_pos ;
298+ };
299+
300+ struct secp256k1_strauss_state {
301+ secp256k1_gej * prej ;
302+ secp256k1_fe * zr ;
303+ secp256k1_ge * pre_a ;
304+ #ifdef USE_ENDOMORPHISM
305+ secp256k1_ge * pre_a_lam ;
306+ #endif
307+ struct secp256k1_strauss_point_state * ps ;
308+ };
309+
310+ static void secp256k1_ecmult_strauss_wnaf (const secp256k1_ecmult_context * ctx , const struct secp256k1_strauss_state * state , secp256k1_gej * r , int num , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
311+ secp256k1_ge tmpa ;
312+ secp256k1_fe Z ;
313+ #ifdef USE_ENDOMORPHISM
314+ /* Splitted G factors. */
315+ secp256k1_scalar ng_1 , ng_128 ;
316+ int wnaf_ng_1 [129 ];
317+ int bits_ng_1 = 0 ;
318+ int wnaf_ng_128 [129 ];
319+ int bits_ng_128 = 0 ;
320+ #else
306321 int wnaf_ng [256 ];
307- int bits_ng ;
322+ int bits_ng = 0 ;
308323#endif
309324 int i ;
310- int bits ;
325+ int bits = 0 ;
326+ int np ;
327+ int no = 0 ;
311328
329+ for (np = 0 ; np < num ; ++ np ) {
330+ if (secp256k1_scalar_is_zero (& na [np ]) || secp256k1_gej_is_infinity (& a [np ])) {
331+ continue ;
332+ }
333+ state -> ps [no ].input_pos = np ;
312334#ifdef USE_ENDOMORPHISM
313- /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
314- secp256k1_scalar_split_lambda (& na_1 , & na_lam , na );
315-
316- /* build wnaf representation for na_1 and na_lam. */
317- bits_na_1 = secp256k1_ecmult_wnaf (wnaf_na_1 , 130 , & na_1 , WINDOW_A );
318- bits_na_lam = secp256k1_ecmult_wnaf (wnaf_na_lam , 130 , & na_lam , WINDOW_A );
319- VERIFY_CHECK (bits_na_1 <= 130 );
320- VERIFY_CHECK (bits_na_lam <= 130 );
321- bits = bits_na_1 ;
322- if (bits_na_lam > bits ) {
323- bits = bits_na_lam ;
324- }
335+ /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
336+ secp256k1_scalar_split_lambda (& state -> ps [no ].na_1 , & state -> ps [no ].na_lam , & na [np ]);
337+
338+ /* build wnaf representation for na_1 and na_lam. */
339+ state -> ps [no ].bits_na_1 = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_1 , 130 , & state -> ps [no ].na_1 , WINDOW_A );
340+ state -> ps [no ].bits_na_lam = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_lam , 130 , & state -> ps [no ].na_lam , WINDOW_A );
341+ VERIFY_CHECK (state -> ps [no ].bits_na_1 <= 130 );
342+ VERIFY_CHECK (state -> ps [no ].bits_na_lam <= 130 );
343+ if (state -> ps [no ].bits_na_1 > bits ) {
344+ bits = state -> ps [no ].bits_na_1 ;
345+ }
346+ if (state -> ps [no ].bits_na_lam > bits ) {
347+ bits = state -> ps [no ].bits_na_lam ;
348+ }
325349#else
326- /* build wnaf representation for na. */
327- bits_na = secp256k1_ecmult_wnaf (wnaf_na , 256 , na , WINDOW_A );
328- bits = bits_na ;
350+ /* build wnaf representation for na. */
351+ state -> ps [no ].bits_na = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na , 256 , & na [np ], WINDOW_A );
352+ if (state -> ps [no ].bits_na > bits ) {
353+ bits = state -> ps [no ].bits_na ;
354+ }
329355#endif
356+ ++ no ;
357+ }
330358
331359 /* Calculate odd multiples of a.
332360 * All multiples are brought to the same Z 'denominator', which is stored
@@ -338,29 +366,51 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
338366 * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
339367 * isomorphism to efficiently add with a known Z inverse.
340368 */
341- secp256k1_ecmult_odd_multiples_table_globalz_windowa (pre_a , & Z , a );
369+ if (no > 0 ) {
370+ /* Compute the odd multiples in Jacobian form. */
371+ secp256k1_ecmult_odd_multiples_table (ECMULT_TABLE_SIZE (WINDOW_A ), state -> prej , state -> zr , & a [state -> ps [0 ].input_pos ]);
372+ for (np = 1 ; np < no ; ++ np ) {
373+ secp256k1_gej tmp = a [state -> ps [np ].input_pos ];
374+ #ifdef VERIFY
375+ secp256k1_fe_normalize_var (& (state -> prej [(np - 1 ) * ECMULT_TABLE_SIZE (WINDOW_A ) + ECMULT_TABLE_SIZE (WINDOW_A ) - 1 ].z ));
376+ #endif
377+ secp256k1_gej_rescale (& tmp , & (state -> prej [(np - 1 ) * ECMULT_TABLE_SIZE (WINDOW_A ) + ECMULT_TABLE_SIZE (WINDOW_A ) - 1 ].z ));
378+ secp256k1_ecmult_odd_multiples_table (ECMULT_TABLE_SIZE (WINDOW_A ), state -> prej + np * ECMULT_TABLE_SIZE (WINDOW_A ), state -> zr + np * ECMULT_TABLE_SIZE (WINDOW_A ), & tmp );
379+ secp256k1_fe_mul (state -> zr + np * ECMULT_TABLE_SIZE (WINDOW_A ), state -> zr + np * ECMULT_TABLE_SIZE (WINDOW_A ), & (a [state -> ps [np ].input_pos ].z ));
380+ }
381+ /* Bring them to the same Z denominator. */
382+ secp256k1_ge_globalz_set_table_gej (ECMULT_TABLE_SIZE (WINDOW_A ) * no , state -> pre_a , & Z , state -> prej , state -> zr );
383+ } else {
384+ secp256k1_fe_set_int (& Z , 1 );
385+ }
342386
343387#ifdef USE_ENDOMORPHISM
344- for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
345- secp256k1_ge_mul_lambda (& pre_a_lam [i ], & pre_a [i ]);
388+ for (np = 0 ; np < no ; ++ np ) {
389+ for (i = 0 ; i < ECMULT_TABLE_SIZE (WINDOW_A ); i ++ ) {
390+ secp256k1_ge_mul_lambda (& state -> pre_a_lam [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ], & state -> pre_a [np * ECMULT_TABLE_SIZE (WINDOW_A ) + i ]);
391+ }
346392 }
347393
348- /* 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) */
349- secp256k1_scalar_split_128 (& ng_1 , & ng_128 , ng );
394+ if (ng ) {
395+ /* 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) */
396+ secp256k1_scalar_split_128 (& ng_1 , & ng_128 , ng );
350397
351- /* Build wnaf representation for ng_1 and ng_128 */
352- bits_ng_1 = secp256k1_ecmult_wnaf (wnaf_ng_1 , 129 , & ng_1 , WINDOW_G );
353- bits_ng_128 = secp256k1_ecmult_wnaf (wnaf_ng_128 , 129 , & ng_128 , WINDOW_G );
354- if (bits_ng_1 > bits ) {
355- bits = bits_ng_1 ;
356- }
357- if (bits_ng_128 > bits ) {
358- bits = bits_ng_128 ;
398+ /* Build wnaf representation for ng_1 and ng_128 */
399+ bits_ng_1 = secp256k1_ecmult_wnaf (wnaf_ng_1 , 129 , & ng_1 , WINDOW_G );
400+ bits_ng_128 = secp256k1_ecmult_wnaf (wnaf_ng_128 , 129 , & ng_128 , WINDOW_G );
401+ if (bits_ng_1 > bits ) {
402+ bits = bits_ng_1 ;
403+ }
404+ if (bits_ng_128 > bits ) {
405+ bits = bits_ng_128 ;
406+ }
359407 }
360408#else
361- bits_ng = secp256k1_ecmult_wnaf (wnaf_ng , 256 , ng , WINDOW_G );
362- if (bits_ng > bits ) {
363- bits = bits_ng ;
409+ if (ng ) {
410+ bits_ng = secp256k1_ecmult_wnaf (wnaf_ng , 256 , ng , WINDOW_G );
411+ if (bits_ng > bits ) {
412+ bits = bits_ng ;
413+ }
364414 }
365415#endif
366416
@@ -370,13 +420,15 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
370420 int n ;
371421 secp256k1_gej_double_var (r , r , NULL );
372422#ifdef USE_ENDOMORPHISM
373- if (i < bits_na_1 && (n = wnaf_na_1 [i ])) {
374- ECMULT_TABLE_GET_GE (& tmpa , pre_a , n , WINDOW_A );
375- secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
376- }
377- if (i < bits_na_lam && (n = wnaf_na_lam [i ])) {
378- ECMULT_TABLE_GET_GE (& tmpa , pre_a_lam , n , WINDOW_A );
379- secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
423+ for (np = 0 ; np < no ; ++ np ) {
424+ if (i < state -> ps [np ].bits_na_1 && (n = state -> ps [np ].wnaf_na_1 [i ])) {
425+ ECMULT_TABLE_GET_GE (& tmpa , state -> pre_a + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
426+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
427+ }
428+ if (i < state -> ps [np ].bits_na_lam && (n = state -> ps [np ].wnaf_na_lam [i ])) {
429+ ECMULT_TABLE_GET_GE (& tmpa , state -> pre_a_lam + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
430+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
431+ }
380432 }
381433 if (i < bits_ng_1 && (n = wnaf_ng_1 [i ])) {
382434 ECMULT_TABLE_GET_GE_STORAGE (& tmpa , * ctx -> pre_g , n , WINDOW_G );
@@ -387,9 +439,11 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
387439 secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
388440 }
389441#else
390- if (i < bits_na && (n = wnaf_na [i ])) {
391- ECMULT_TABLE_GET_GE (& tmpa , pre_a , n , WINDOW_A );
392- secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
442+ for (np = 0 ; np < no ; ++ np ) {
443+ if (i < state -> ps [np ].bits_na && (n = state -> ps [np ].wnaf_na [i ])) {
444+ ECMULT_TABLE_GET_GE (& tmpa , state -> pre_a + np * ECMULT_TABLE_SIZE (WINDOW_A ), n , WINDOW_A );
445+ secp256k1_gej_add_ge_var (r , r , & tmpa , NULL );
446+ }
393447 }
394448 if (i < bits_ng && (n = wnaf_ng [i ])) {
395449 ECMULT_TABLE_GET_GE_STORAGE (& tmpa , * ctx -> pre_g , n , WINDOW_G );
@@ -403,4 +457,94 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
403457 }
404458}
405459
460+ static void secp256k1_ecmult (const secp256k1_ecmult_context * ctx , secp256k1_gej * r , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
461+ secp256k1_gej prej [ECMULT_TABLE_SIZE (WINDOW_A )];
462+ secp256k1_fe zr [ECMULT_TABLE_SIZE (WINDOW_A )];
463+ secp256k1_ge pre_a [ECMULT_TABLE_SIZE (WINDOW_A )];
464+ struct secp256k1_strauss_point_state ps [1 ];
465+ #ifdef USE_ENDOMORPHISM
466+ secp256k1_ge pre_a_lam [ECMULT_TABLE_SIZE (WINDOW_A )];
467+ #endif
468+ struct secp256k1_strauss_state state ;
469+
470+ state .prej = prej ;
471+ state .zr = zr ;
472+ state .pre_a = pre_a ;
473+ #ifdef USE_ENDOMORPHISM
474+ state .pre_a_lam = pre_a_lam ;
475+ #endif
476+ state .ps = ps ;
477+ secp256k1_ecmult_strauss_wnaf (ctx , & state , r , 1 , a , na , ng );
478+ }
479+
480+ static int secp256k1_ecmult_multi_split_strauss_wnaf (const secp256k1_ecmult_context * ctx , secp256k1_scratch * scratch , secp256k1_gej * r , const secp256k1_scalar * inp_g_sc , secp256k1_ecmult_multi_callback cb , void * cbdata , size_t n ) {
481+ secp256k1_gej * points ;
482+ secp256k1_scalar * scalars ;
483+ secp256k1_gej acc ;
484+ size_t in_pos = 0 , out_pos = 0 ;
485+ int first = 1 ;
486+
487+ #ifdef USE_ENDOMORPHISM
488+ static const size_t point_size = (sizeof (secp256k1_gej ) + sizeof (secp256k1_fe ) + sizeof (secp256k1_ge ) * 2 ) * ECMULT_TABLE_SIZE (WINDOW_A ) + sizeof (struct secp256k1_strauss_point_state ) + sizeof (secp256k1_gej ) + sizeof (secp256k1_scalar );
489+ #else
490+ static const size_t point_size = (sizeof (secp256k1_gej ) + sizeof (secp256k1_fe ) + sizeof (secp256k1_ge )) * ECMULT_TABLE_SIZE (WINDOW_A ) + sizeof (struct secp256k1_strauss_point_state ) + sizeof (secp256k1_gej ) + sizeof (secp256k1_scalar );
491+ #endif
492+
493+ size_t max_points = secp256k1_scratch_max_allocation (scratch , 6 ) / point_size ;
494+ size_t n_batches , points_per_batch ;
495+ struct secp256k1_strauss_state state ;
496+
497+ if (max_points == 0 ) return 0 ;
498+ if (max_points > 160 ) max_points = 160 ; /* At this point, gains are not longer compensating for locality degradation */
499+ n_batches = (n + max_points - 1 ) / max_points ;
500+ points_per_batch = (n + n_batches - 1 ) / n_batches ;
501+
502+ /* Attempt to allocate sufficient space for Strauss */
503+ while (!secp256k1_scratch_resize (scratch , max_points * point_size , 6 )) {
504+ max_points /= 2 ;
505+ if (max_points == 0 ) {
506+ return 0 ;
507+ }
508+ }
509+
510+ secp256k1_scratch_reset (scratch );
511+ points = (secp256k1_gej * )secp256k1_scratch_alloc (scratch , max_points * sizeof (secp256k1_gej ));
512+ scalars = (secp256k1_scalar * )secp256k1_scratch_alloc (scratch , max_points * sizeof (secp256k1_scalar ));
513+ state .prej = (secp256k1_gej * )secp256k1_scratch_alloc (scratch , max_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_gej ));
514+ state .zr = (secp256k1_fe * )secp256k1_scratch_alloc (scratch , max_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_fe ));
515+ #ifdef USE_ENDOMORPHISM
516+ state .pre_a = (secp256k1_ge * )secp256k1_scratch_alloc (scratch , max_points * 2 * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_ge ));
517+ state .pre_a_lam = state .pre_a + max_points * ECMULT_TABLE_SIZE (WINDOW_A );
518+ #else
519+ state .pre_a = (secp256k1_ge * )secp256k1_scratch_alloc (scratch , max_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_ge ));
520+ #endif
521+ state .ps = (struct secp256k1_strauss_point_state * )secp256k1_scratch_alloc (scratch , max_points * sizeof (struct secp256k1_strauss_point_state ));
522+
523+ if (n == 0 && inp_g_sc ) {
524+ secp256k1_ecmult_strauss_wnaf (ctx , & state , r , 0 , NULL , NULL , inp_g_sc );
525+ return 1 ;
526+ }
527+
528+ while (in_pos < n ) {
529+ secp256k1_ge point ;
530+ if (!cb (& scalars [out_pos ], & point , in_pos , cbdata )) return 0 ;
531+ secp256k1_gej_set_ge (& points [out_pos ], & point );
532+ ++ in_pos ;
533+ ++ out_pos ;
534+ if (out_pos == points_per_batch || in_pos == n ) {
535+ secp256k1_ecmult_strauss_wnaf (ctx , & state , first ? r : & acc , out_pos , points , scalars , first ? inp_g_sc : NULL );
536+ if (!first ) {
537+ secp256k1_gej_add_var (r , r , & acc , NULL );
538+ }
539+ first = 0 ;
540+ out_pos = 0 ;
541+ }
542+ }
543+ return 1 ;
544+ }
545+
546+ static int secp256k1_ecmult_multi (const secp256k1_ecmult_context * ctx , secp256k1_scratch * scratch , secp256k1_gej * r , const secp256k1_scalar * inp_g_sc , secp256k1_ecmult_multi_callback cb , void * cbdata , size_t n ) {
547+ return secp256k1_ecmult_multi_split_strauss_wnaf (ctx , scratch , r , inp_g_sc , cb , cbdata , n );
548+ }
549+
406550#endif /* SECP256K1_ECMULT_IMPL_H */
0 commit comments