Skip to content

Commit 19b9927

Browse files
committedMar 30, 2021
Eliminate the use of points and scalars from secp256k1_ecmult_strauss_batch.
We have secp256k1_ecmult_strauss_wnaf invoke the callback itself.
1 parent 59745ee commit 19b9927

File tree

1 file changed

+61
-20
lines changed

1 file changed

+61
-20
lines changed
 

‎src/ecmult_impl.h

+61-20
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ struct secp256k1_strauss_state {
455455
struct secp256k1_strauss_point_state* ps;
456456
};
457457

458-
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
458+
typedef int (secp256k1_ecmult_strauss_multi_callback)(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data);
459+
460+
static int secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, 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) {
459461
secp256k1_ge tmpa;
460462
secp256k1_fe Z;
461463
/* Splitted G factors. */
@@ -471,13 +473,17 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
471473

472474
secp256k1_fe_set_int(&Z, 1);
473475
for (np = 0; np < num; ++np) {
474-
secp256k1_gej tmp;
475-
secp256k1_scalar na_1, na_lam;
476-
if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
476+
secp256k1_gej a;
477+
secp256k1_fe az;
478+
secp256k1_scalar na, na_1, na_lam;
479+
480+
if (!cb(&na, &a, np + cb_offset, cbdata)) return 0;
481+
if (secp256k1_scalar_is_zero(&na) || secp256k1_gej_is_infinity(&a)) {
477482
continue;
478483
}
484+
479485
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
480-
secp256k1_scalar_split_lambda(&na_1, &na_lam, &na[np]);
486+
secp256k1_scalar_split_lambda(&na_1, &na_lam, &na);
481487

482488
/* build wnaf representation for na_1 and na_lam. */
483489
state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A);
@@ -501,16 +507,16 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
501507
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
502508
* isomorphism to efficiently add with a known Z inverse.
503509
*/
504-
tmp = a[np];
510+
az = a.z;
505511
if (no) {
506512
#ifdef VERIFY
507513
secp256k1_fe_normalize_var(&Z);
508514
#endif
509-
secp256k1_gej_rescale(&tmp, &Z);
515+
secp256k1_gej_rescale(&a, &Z);
510516
}
511-
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), &tmp);
512-
if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z));
513-
Z = tmp.z;
517+
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), &a);
518+
if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &az);
519+
Z = a.z;
514520

515521
++no;
516522
}
@@ -569,30 +575,68 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
569575
if (!r->infinity) {
570576
secp256k1_fe_mul(&r->z, &r->z, &Z);
571577
}
578+
579+
return 1;
580+
}
581+
582+
struct secp256k1_ecmult_array_cb_data {
583+
const secp256k1_scalar *na;
584+
const secp256k1_gej *a;
585+
};
586+
587+
static int secp256k1_ecmult_array_cb(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data) {
588+
struct secp256k1_ecmult_array_cb_data *array_data = data;
589+
*sc = array_data->na[idx];
590+
if (array_data->a) {
591+
*pt = array_data->a[idx];
592+
return 1;
593+
} else {
594+
return secp256k1_scalar_is_zero(sc);
595+
}
572596
}
573597

574598
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
575599
secp256k1_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)];
576600
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
577601
struct secp256k1_strauss_point_state ps[1];
578602
struct secp256k1_strauss_state state;
603+
struct secp256k1_ecmult_array_cb_data data;
579604

580605
state.aux = aux;
581606
state.pre_a = pre_a;
582607
state.ps = ps;
583-
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
608+
data.na = na;
609+
data.a = a;
610+
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, &secp256k1_ecmult_array_cb, &data, 0, ng);
584611
}
585612

586613
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
587614
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);
588615
return n_points*point_size;
589616
}
590617

618+
struct secp256k1_ecmult_adaptor_cb_data {
619+
secp256k1_ecmult_multi_callback *cb;
620+
void *data;
621+
};
622+
623+
static int secp256k1_ecmult_adaptor_cb(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data) {
624+
secp256k1_ge tmp;
625+
struct secp256k1_ecmult_adaptor_cb_data *adaptor_data = data;
626+
int result = adaptor_data->cb(sc, &tmp, idx, adaptor_data->data);
627+
628+
if (result) {
629+
secp256k1_gej_set_ge(pt, &tmp);
630+
}
631+
632+
return result;
633+
}
634+
591635
static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, 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_points, size_t cb_offset) {
592636
secp256k1_gej* points;
593637
secp256k1_scalar* scalars;
638+
struct secp256k1_ecmult_adaptor_cb_data adaptor_data;
594639
struct secp256k1_strauss_state state;
595-
size_t i;
596640
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
597641

598642
secp256k1_gej_set_infinity(r);
@@ -602,6 +646,8 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
602646

603647
points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej));
604648
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
649+
adaptor_data.cb = cb;
650+
adaptor_data.data = cbdata;
605651
state.aux = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
606652
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
607653
state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state));
@@ -611,15 +657,10 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
611657
return 0;
612658
}
613659

614-
for (i = 0; i < n_points; i++) {
615-
secp256k1_ge point;
616-
if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) {
617-
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
618-
return 0;
619-
}
620-
secp256k1_gej_set_ge(&points[i], &point);
660+
if (!secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, &secp256k1_ecmult_adaptor_cb, &adaptor_data, cb_offset, inp_g_sc)) {
661+
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
662+
return 0;
621663
}
622-
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
623664
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
624665
return 1;
625666
}

0 commit comments

Comments
 (0)