Skip to content

Commit 8242379

Browse files
Eliminate the use of points and scalars from secp256k1_ecmult_strauss_batch.
We have secp256k1_ecmult_strauss_wnaf invoke the callback itself.
1 parent 5aea2e8 commit 8242379

File tree

1 file changed

+60
-19
lines changed

1 file changed

+60
-19
lines changed

src/ecmult_impl.h

+60-19
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ struct secp256k1_strauss_state {
233233
struct secp256k1_strauss_point_state* ps;
234234
};
235235

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) {
237239
secp256k1_ge tmpa;
238240
secp256k1_fe Z;
239241
/* Split G factors. */
@@ -249,13 +251,17 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
249251

250252
secp256k1_fe_set_int(&Z, 1);
251253
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)) {
255260
continue;
256261
}
262+
257263
/* 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);
259265

260266
/* build wnaf representation for na_1 and na_lam. */
261267
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 *
279285
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
280286
* isomorphism to efficiently add with a known Z inverse.
281287
*/
282-
tmp = a[np];
288+
az = a.z;
283289
if (no) {
284290
#ifdef VERIFY
285291
secp256k1_fe_normalize_var(&Z);
286292
#endif
287-
secp256k1_gej_rescale(&tmp, &Z);
293+
secp256k1_gej_rescale(&a, &Z);
288294
}
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);
291297

292298
++no;
293299
}
@@ -344,30 +350,68 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
344350
if (!r->infinity) {
345351
secp256k1_fe_mul(&r->z, &r->z, &Z);
346352
}
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+
}
347371
}
348372

349373
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
350374
secp256k1_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)];
351375
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
352376
struct secp256k1_strauss_point_state ps[1];
353377
struct secp256k1_strauss_state state;
378+
struct secp256k1_ecmult_array_cb_data data;
354379

355380
state.aux = aux;
356381
state.pre_a = pre_a;
357382
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);
359386
}
360387

361388
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
362389
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);
363390
return n_points*point_size;
364391
}
365392

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+
366410
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) {
367411
secp256k1_gej* points;
368412
secp256k1_scalar* scalars;
413+
struct secp256k1_ecmult_adaptor_cb_data adaptor_data;
369414
struct secp256k1_strauss_state state;
370-
size_t i;
371415
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
372416

373417
secp256k1_gej_set_infinity(r);
@@ -380,6 +424,8 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
380424
* constant and strauss_scratch_size accordingly. */
381425
points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej));
382426
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
427+
adaptor_data.cb = cb;
428+
adaptor_data.data = cbdata;
383429
state.aux = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
384430
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
385431
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
389435
return 0;
390436
}
391437

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;
399441
}
400-
secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
401442
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
402443
return 1;
403444
}

0 commit comments

Comments
 (0)