@@ -233,7 +233,9 @@ struct secp256k1_strauss_state {
233
233
struct secp256k1_strauss_point_state * ps ;
234
234
};
235
235
236
- static void secp256k1_ecmult_strauss_wnaf (const struct secp256k1_strauss_state * state , secp256k1_gej * r , size_t num , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
236
+ typedef int (secp256k1_ecmult_strauss_multi_callback )(secp256k1_scalar * sc , secp256k1_gej * pt , size_t idx , void * data );
237
+
238
+ static int secp256k1_ecmult_strauss_wnaf (const struct secp256k1_strauss_state * state , secp256k1_gej * r , size_t num , secp256k1_ecmult_strauss_multi_callback cb , void * cbdata , size_t cb_offset , const secp256k1_scalar * ng ) {
237
239
secp256k1_ge tmpa ;
238
240
secp256k1_fe Z ;
239
241
/* Split G factors. */
@@ -249,13 +251,17 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
249
251
250
252
secp256k1_fe_set_int (& Z , 1 );
251
253
for (np = 0 ; np < num ; ++ np ) {
252
- secp256k1_gej tmp ;
253
- secp256k1_scalar na_1 , na_lam ;
254
- if (secp256k1_scalar_is_zero (& na [np ]) || secp256k1_gej_is_infinity (& a [np ])) {
254
+ secp256k1_gej a ;
255
+ secp256k1_fe az ;
256
+ secp256k1_scalar na , na_1 , na_lam ;
257
+
258
+ if (!cb (& na , & a , np + cb_offset , cbdata )) return 0 ;
259
+ if (secp256k1_scalar_is_zero (& na ) || secp256k1_gej_is_infinity (& a )) {
255
260
continue ;
256
261
}
262
+
257
263
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
258
- secp256k1_scalar_split_lambda (& na_1 , & na_lam , & na [ np ] );
264
+ secp256k1_scalar_split_lambda (& na_1 , & na_lam , & na );
259
265
260
266
/* build wnaf representation for na_1 and na_lam. */
261
267
state -> ps [no ].bits_na_1 = secp256k1_ecmult_wnaf (state -> ps [no ].wnaf_na_1 , 129 , & na_1 , WINDOW_A );
@@ -279,15 +285,15 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
279
285
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
280
286
* isomorphism to efficiently add with a known Z inverse.
281
287
*/
282
- tmp = a [ np ] ;
288
+ az = a . z ;
283
289
if (no ) {
284
290
#ifdef VERIFY
285
291
secp256k1_fe_normalize_var (& Z );
286
292
#endif
287
- secp256k1_gej_rescale (& tmp , & Z );
293
+ secp256k1_gej_rescale (& a , & Z );
288
294
}
289
- secp256k1_ecmult_odd_multiples_table (ECMULT_TABLE_SIZE (WINDOW_A ), state -> pre_a + no * ECMULT_TABLE_SIZE (WINDOW_A ), state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), & Z , & tmp );
290
- if (no ) secp256k1_fe_mul (state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), & ( a [ np ]. z ) );
295
+ secp256k1_ecmult_odd_multiples_table (ECMULT_TABLE_SIZE (WINDOW_A ), state -> pre_a + no * ECMULT_TABLE_SIZE (WINDOW_A ), state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), & Z , & a );
296
+ if (no ) secp256k1_fe_mul (state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), state -> aux + no * ECMULT_TABLE_SIZE (WINDOW_A ), & az );
291
297
292
298
++ no ;
293
299
}
@@ -344,30 +350,68 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
344
350
if (!r -> infinity ) {
345
351
secp256k1_fe_mul (& r -> z , & r -> z , & Z );
346
352
}
353
+
354
+ return 1 ;
355
+ }
356
+
357
+ struct secp256k1_ecmult_array_cb_data {
358
+ const secp256k1_scalar * na ;
359
+ const secp256k1_gej * a ;
360
+ };
361
+
362
+ static int secp256k1_ecmult_array_cb (secp256k1_scalar * sc , secp256k1_gej * pt , size_t idx , void * data ) {
363
+ struct secp256k1_ecmult_array_cb_data * array_data = data ;
364
+ * sc = array_data -> na [idx ];
365
+ if (array_data -> a ) {
366
+ * pt = array_data -> a [idx ];
367
+ return 1 ;
368
+ } else {
369
+ return secp256k1_scalar_is_zero (sc );
370
+ }
347
371
}
348
372
349
373
static void secp256k1_ecmult (secp256k1_gej * r , const secp256k1_gej * a , const secp256k1_scalar * na , const secp256k1_scalar * ng ) {
350
374
secp256k1_fe aux [ECMULT_TABLE_SIZE (WINDOW_A )];
351
375
secp256k1_ge pre_a [ECMULT_TABLE_SIZE (WINDOW_A )];
352
376
struct secp256k1_strauss_point_state ps [1 ];
353
377
struct secp256k1_strauss_state state ;
378
+ struct secp256k1_ecmult_array_cb_data data ;
354
379
355
380
state .aux = aux ;
356
381
state .pre_a = pre_a ;
357
382
state .ps = ps ;
358
- secp256k1_ecmult_strauss_wnaf (& state , r , 1 , a , na , ng );
383
+ data .na = na ;
384
+ data .a = a ;
385
+ secp256k1_ecmult_strauss_wnaf (& state , r , 1 , & secp256k1_ecmult_array_cb , & data , 0 , ng );
359
386
}
360
387
361
388
static size_t secp256k1_strauss_scratch_size (size_t n_points ) {
362
389
static const size_t point_size = (sizeof (secp256k1_ge ) + sizeof (secp256k1_fe )) * ECMULT_TABLE_SIZE (WINDOW_A ) + sizeof (struct secp256k1_strauss_point_state ) + sizeof (secp256k1_gej ) + sizeof (secp256k1_scalar );
363
390
return n_points * point_size ;
364
391
}
365
392
393
+ struct secp256k1_ecmult_adaptor_cb_data {
394
+ secp256k1_ecmult_multi_callback * cb ;
395
+ void * data ;
396
+ };
397
+
398
+ static int secp256k1_ecmult_adaptor_cb (secp256k1_scalar * sc , secp256k1_gej * pt , size_t idx , void * data ) {
399
+ secp256k1_ge tmp ;
400
+ struct secp256k1_ecmult_adaptor_cb_data * adaptor_data = data ;
401
+ int result = adaptor_data -> cb (sc , & tmp , idx , adaptor_data -> data );
402
+
403
+ if (result ) {
404
+ secp256k1_gej_set_ge (pt , & tmp );
405
+ }
406
+
407
+ return result ;
408
+ }
409
+
366
410
static int secp256k1_ecmult_strauss_batch (const secp256k1_callback * error_callback , secp256k1_scratch * scratch , secp256k1_gej * r , const secp256k1_scalar * inp_g_sc , secp256k1_ecmult_multi_callback cb , void * cbdata , size_t n_points , size_t cb_offset ) {
367
411
secp256k1_gej * points ;
368
412
secp256k1_scalar * scalars ;
413
+ struct secp256k1_ecmult_adaptor_cb_data adaptor_data ;
369
414
struct secp256k1_strauss_state state ;
370
- size_t i ;
371
415
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint (error_callback , scratch );
372
416
373
417
secp256k1_gej_set_infinity (r );
@@ -380,6 +424,8 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
380
424
* constant and strauss_scratch_size accordingly. */
381
425
points = (secp256k1_gej * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (secp256k1_gej ));
382
426
scalars = (secp256k1_scalar * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (secp256k1_scalar ));
427
+ adaptor_data .cb = cb ;
428
+ adaptor_data .data = cbdata ;
383
429
state .aux = (secp256k1_fe * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_fe ));
384
430
state .pre_a = (secp256k1_ge * )secp256k1_scratch_alloc (error_callback , scratch , n_points * ECMULT_TABLE_SIZE (WINDOW_A ) * sizeof (secp256k1_ge ));
385
431
state .ps = (struct secp256k1_strauss_point_state * )secp256k1_scratch_alloc (error_callback , scratch , n_points * sizeof (struct secp256k1_strauss_point_state ));
@@ -389,15 +435,10 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
389
435
return 0 ;
390
436
}
391
437
392
- for (i = 0 ; i < n_points ; i ++ ) {
393
- secp256k1_ge point ;
394
- if (!cb (& scalars [i ], & point , i + cb_offset , cbdata )) {
395
- secp256k1_scratch_apply_checkpoint (error_callback , scratch , scratch_checkpoint );
396
- return 0 ;
397
- }
398
- secp256k1_gej_set_ge (& points [i ], & point );
438
+ if (!secp256k1_ecmult_strauss_wnaf (& state , r , n_points , & secp256k1_ecmult_adaptor_cb , & adaptor_data , cb_offset , inp_g_sc )) {
439
+ secp256k1_scratch_apply_checkpoint (error_callback , scratch , scratch_checkpoint );
440
+ return 0 ;
399
441
}
400
- secp256k1_ecmult_strauss_wnaf (& state , r , n_points , points , scalars , inp_g_sc );
401
442
secp256k1_scratch_apply_checkpoint (error_callback , scratch , scratch_checkpoint );
402
443
return 1 ;
403
444
}
0 commit comments