Skip to content

Commit 764bf7f

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 80fc6f1 commit 764bf7f

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
@@ -228,7 +228,9 @@ struct secp256k1_strauss_state {
228228
struct secp256k1_strauss_point_state* ps;
229229
};
230230

231-
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) {
231+
typedef int (secp256k1_ecmult_strauss_multi_callback)(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data);
232+
233+
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) {
232234
secp256k1_ge tmpa;
233235
secp256k1_fe Z;
234236
/* Split G factors. */
@@ -244,13 +246,17 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
244246

245247
secp256k1_fe_set_int(&Z, 1);
246248
for (np = 0; np < num; ++np) {
247-
secp256k1_gej tmp;
248-
secp256k1_scalar na_1, na_lam;
249-
if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
249+
secp256k1_gej a;
250+
secp256k1_fe az;
251+
secp256k1_scalar na, na_1, na_lam;
252+
253+
if (!cb(&na, &a, np + cb_offset, cbdata)) return 0;
254+
if (secp256k1_scalar_is_zero(&na) || secp256k1_gej_is_infinity(&a)) {
250255
continue;
251256
}
257+
252258
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
253-
secp256k1_scalar_split_lambda(&na_1, &na_lam, &na[np]);
259+
secp256k1_scalar_split_lambda(&na_1, &na_lam, &na);
254260

255261
/* build wnaf representation for na_1 and na_lam. */
256262
state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A);
@@ -274,15 +280,15 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
274280
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
275281
* isomorphism to efficiently add with a known Z inverse.
276282
*/
277-
tmp = a[np];
283+
az = a.z;
278284
if (no) {
279285
#ifdef VERIFY
280286
secp256k1_fe_normalize_var(&Z);
281287
#endif
282-
secp256k1_gej_rescale(&tmp, &Z);
288+
secp256k1_gej_rescale(&a, &Z);
283289
}
284-
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);
285-
if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z));
290+
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);
291+
if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &az);
286292

287293
++no;
288294
}
@@ -339,30 +345,68 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
339345
if (!r->infinity) {
340346
secp256k1_fe_mul(&r->z, &r->z, &Z);
341347
}
348+
349+
return 1;
350+
}
351+
352+
struct secp256k1_ecmult_array_cb_data {
353+
const secp256k1_scalar *na;
354+
const secp256k1_gej *a;
355+
};
356+
357+
static int secp256k1_ecmult_array_cb(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data) {
358+
struct secp256k1_ecmult_array_cb_data *array_data = data;
359+
*sc = array_data->na[idx];
360+
if (array_data->a) {
361+
*pt = array_data->a[idx];
362+
return 1;
363+
} else {
364+
return secp256k1_scalar_is_zero(sc);
365+
}
342366
}
343367

344368
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
345369
secp256k1_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)];
346370
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
347371
struct secp256k1_strauss_point_state ps[1];
348372
struct secp256k1_strauss_state state;
373+
struct secp256k1_ecmult_array_cb_data data;
349374

350375
state.aux = aux;
351376
state.pre_a = pre_a;
352377
state.ps = ps;
353-
secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
378+
data.na = na;
379+
data.a = a;
380+
secp256k1_ecmult_strauss_wnaf(&state, r, 1, &secp256k1_ecmult_array_cb, &data, 0, ng);
354381
}
355382

356383
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
357384
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);
358385
return n_points*point_size;
359386
}
360387

388+
struct secp256k1_ecmult_adaptor_cb_data {
389+
secp256k1_ecmult_multi_callback *cb;
390+
void *data;
391+
};
392+
393+
static int secp256k1_ecmult_adaptor_cb(secp256k1_scalar *sc, secp256k1_gej *pt, size_t idx, void *data) {
394+
secp256k1_ge tmp;
395+
struct secp256k1_ecmult_adaptor_cb_data *adaptor_data = data;
396+
int result = adaptor_data->cb(sc, &tmp, idx, adaptor_data->data);
397+
398+
if (result) {
399+
secp256k1_gej_set_ge(pt, &tmp);
400+
}
401+
402+
return result;
403+
}
404+
361405
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) {
362406
secp256k1_gej* points;
363407
secp256k1_scalar* scalars;
408+
struct secp256k1_ecmult_adaptor_cb_data adaptor_data;
364409
struct secp256k1_strauss_state state;
365-
size_t i;
366410
const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch);
367411

368412
secp256k1_gej_set_infinity(r);
@@ -372,6 +416,8 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
372416

373417
points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej));
374418
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
419+
adaptor_data.cb = cb;
420+
adaptor_data.data = cbdata;
375421
state.aux = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
376422
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
377423
state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state));
@@ -381,15 +427,10 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
381427
return 0;
382428
}
383429

384-
for (i = 0; i < n_points; i++) {
385-
secp256k1_ge point;
386-
if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) {
387-
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
388-
return 0;
389-
}
390-
secp256k1_gej_set_ge(&points[i], &point);
430+
if (!secp256k1_ecmult_strauss_wnaf(&state, r, n_points, &secp256k1_ecmult_adaptor_cb, &adaptor_data, cb_offset, inp_g_sc)) {
431+
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
432+
return 0;
391433
}
392-
secp256k1_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc);
393434
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
394435
return 1;
395436
}

0 commit comments

Comments
 (0)