1
1
/**********************************************************************
2
- * Copyright (c) 2013, 2014 Pieter Wuille *
2
+ * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra *
3
3
* Distributed under the MIT software license, see the accompanying *
4
4
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5
5
**********************************************************************/
@@ -283,50 +283,78 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
283
283
return last_set_bit + 1 ;
284
284
}
285
285
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 {
290
287
#ifdef USE_ENDOMORPHISM
291
- secp256k1_ge pre_a_lam [ECMULT_TABLE_SIZE (WINDOW_A )];
292
288
secp256k1_scalar na_1 , na_lam ;
293
- /* Splitted G factors. */
294
- secp256k1_scalar ng_1 , ng_128 ;
295
289
int wnaf_na_1 [130 ];
296
290
int wnaf_na_lam [130 ];
297
291
int bits_na_1 ;
298
292
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 ;
303
293
#else
304
294
int wnaf_na [256 ];
305
295
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
306
321
int wnaf_ng [256 ];
307
- int bits_ng ;
322
+ int bits_ng = 0 ;
308
323
#endif
309
324
int i ;
310
- int bits ;
325
+ int bits = 0 ;
326
+ int np ;
327
+ int no = 0 ;
311
328
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 ;
312
334
#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
+ }
325
349
#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
+ }
329
355
#endif
356
+ ++ no ;
357
+ }
330
358
331
359
/* Calculate odd multiples of a.
332
360
* 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
338
366
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
339
367
* isomorphism to efficiently add with a known Z inverse.
340
368
*/
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
+ }
342
386
343
387
#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
+ }
346
392
}
347
393
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 );
350
397
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
+ }
359
407
}
360
408
#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
+ }
364
414
}
365
415
#endif
366
416
@@ -370,13 +420,15 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
370
420
int n ;
371
421
secp256k1_gej_double_var (r , r , NULL );
372
422
#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
+ }
380
432
}
381
433
if (i < bits_ng_1 && (n = wnaf_ng_1 [i ])) {
382
434
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
387
439
secp256k1_gej_add_zinv_var (r , r , & tmpa , & Z );
388
440
}
389
441
#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
+ }
393
447
}
394
448
if (i < bits_ng && (n = wnaf_ng [i ])) {
395
449
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
403
457
}
404
458
}
405
459
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
+
406
550
#endif /* SECP256K1_ECMULT_IMPL_H */
0 commit comments